java,一直被开发者戏称为“啰嗦”,但从 jdk 12 到 jdk 17,这门语言发生了显著变化。多个语法层面的增强让 java 更加简洁、表达力更强,也更接近现代语言的风格。本文将带你梳理这六个版本中 java 的关键语法演进。
语法新特性一览
1.switch表达式:不再“陷阱重重”
痛点
传统 switch 不支持返回值,且 break 的遗漏常导致 bug。
新特性(jep 325/354/361)
switch可作为表达式返回值- 引入箭头语法(
->) - 支持多标签匹配
- 使用
yield显式返回值
示例
对 http 状态码进行分类处理,例如:构建统一响应消息或记录错误日志。
string result = switch (statuscode) {
case 200 -> "ok";
case 404 -> "not found";
case 500 -> {
logerror();
yield "server error";
}
default -> "unknown";
};✅ 优势:简洁、安全、不易出错,便于表达逻辑分支。
2. 文本块(text blocks):三引号带来的优雅字符串
痛点
传统多行字符串使用 \n 和拼接,代码难读难维护。
新特性(jep 355/368/378)
- 多行字符串使用
"""定义 - 自动处理缩进和换行
- 支持行连接符
\
示例
构建 sql 查询语句、html 页面模板、json 配置片段。
示例1-sql查询
string query = """
select id, name, email
from users
where status = 'active'
order by created_at desc
""";示例2-html模板
string html = """
<html>
<body>
<h1>welcome, %s!</h1>
</body>
</html>
""".formatted(user.getname());✅ 优势:更易编写 json、sql、html 等嵌入式文本内容。
3.instanceof模式匹配:更聪明的类型判断
痛点
类型判断后必须显式强转,重复又冗余。
新特性(jep 305,jdk 16):
- 支持
instanceof时绑定变量
示例
处理请求参数、事件派发、策略模式中类型判断。
public void process(object input) {
if (input instanceof string s) {
handletext(s);
} else if (input instanceof integer i) {
handlenumber(i);
} else {
throw new illegalargumentexception("unsupported input type");
}
}✅ 优势:去除显式强转,更易读、易写、安全。
4.record类:轻松定义数据载体
痛点
定义一个 pojo 需要写大量样板代码(构造器、getter、equals 等)。
新特性(jep 384,jdk 16)
- 一行代码定义不可变数据类
- 自动生成构造器、访问器、
equals、hashcode、tostring
示例
用于接口响应对象、查询结果封装、消息体定义
示例1-接口响应
public record apiresponse<t>(int code, string message, t data) {}
apiresponse<user> response = new apiresponse<>(200, "ok", user);示例2-封装查询结果
public record usersummary(string name, int postcount) {}
list<usersummary> summaries = userrepository.getsummaries();✅ 优势:专为数据建模而生,简洁且不易出错。
5. 密封类(sealed classes):限制继承范围
痛点
接口或抽象类可以被任意扩展,无法控制子类范围。
新特性(jep 360,jdk 17)
- 使用
sealed修饰类/接口 - 显式声明允许继承的子类(使用
permits)
示例
用于建模流程状态、支付状态、登录结果、事件分发等,确保所有子类都是受控的。
支付状态
public sealed interface paymentresult permits success, failure {}
public final class success implements paymentresult {
string transactionid;
// ...
}
public final class failure implements paymentresult {
string reason;
// ...
}处理支付结果:
void handle(paymentresult result) {
if (result instanceof success s) {
log("success: " + s.transactionid());
} else if (result instanceof failure f) {
log("failure: " + f.reason());
}
}✅ 优势:提供受控扩展,便于在模式匹配和状态建模中使用。
web应用中的实际使用
我们假设web应用有以下功能:用户提交订单后,系统处理订单并返回处理结果(成功、库存不足、支付失败等状态)。
1. 使用record定义响应对象与dto
📌 文件:orderrequest.java
public record orderrequest(long userid, list<long> productids, string paymenttype) {}📌 文件:orderresponse.java
public record orderresponse(string orderno, string message, int code) {}✅ 用途:
- 在 controller 层接收请求/返回响应;
- 省略 getter/setter/构造器;
- 天然不可变,适合并发和函数式风格。
2. 使用sealed+instanceof进行订单结果建模和处理
文件:orderresult.java
public sealed interface orderresult permits ordersuccess, orderfailure {}
public final class ordersuccess implements orderresult {
public final string orderno;
public ordersuccess(string orderno) {
this.orderno = orderno;
}
}
public final class orderfailure implements orderresult {
public final string reason;
public orderfailure(string reason) {
this.reason = reason;
}
}📌 在 service 中处理结果:
public orderresponse handleresult(orderresult result) {
if (result instanceof ordersuccess success) {
return new orderresponse(success.orderno, "下单成功", 200);
} else if (result instanceof orderfailure failure) {
return new orderresponse(null, failure.reason, 500);
}
throw new illegalstateexception("未知结果类型");
}✅ 优点:
- 明确约束返回类型;
- 避免非法实现或扩展;
- 结合
instanceof 模式匹配,写法简洁明了。
3. 使用switch表达式处理支付类型
📌 文件:paymenttype.java(枚举)
public enum paymenttype {
credit_card, wechat, alipay
}📌 在 service 层选择支付服务:
public paymentservice getpaymentservice(paymenttype type) {
return switch (type) {
case credit_card -> creditcardservice;
case wechat -> wechatpayservice;
case alipay -> alipayservice;
};
}✅ 优点:
- 替代 if-else,代码更整洁;
- 编译器检查是否遗漏分支。
4. 使用文本块生成 sql 或消息模板
📌 在 repository 中写动态 sql:
string sql = """
select * from orders
where user_id = ?
and created_at >= date_sub(now(), interval 30 day)
order by created_at desc
""";📌 发送邮件或通知模板:
string content = """
亲爱的用户,您的订单已成功创建:
订单编号:%s
总金额:%.2f 元
感谢您的购买!
""".formatted(orderno, totalamount);✅ 优点:
- 无需拼接;
- 保持结构清晰,适合业务模板开发。
5. controller 层综合调用示例
@restcontroller
@requestmapping("/orders")
public class ordercontroller {
@postmapping
public responseentity<orderresponse> placeorder(@requestbody orderrequest request) {
orderresult result = orderservice.createorder(request);
orderresponse response = orderservice.handleresult(result);
return responseentity.status(response.code()).body(response);
}
}综合收益总结
| 特性 | 实际作用 | 模块 |
|---|---|---|
record | 快速构建不可变 dto 与响应体 | controller/dto |
sealed | 精确限定子类,建模业务状态 | service/domain |
instanceof 模式匹配 | 简洁判断不同业务返回类型 | service |
switch 表达式 | 优雅地分发策略/状态处理 | service |
| 文本块 | 结构化模板与 sql 管理更清晰 | repository/通知模板 |
总结一览表
新特性总结:
| 特性 | jep | java版本 | 优势 |
|---|---|---|---|
switch 表达式 | 325/354/361 | 12-14 | 表达式化、安全简洁 |
| 文本块 | 355/368/378 | 13-15 | 编写多行字符串更自然 |
instanceof 模式匹配 | 305 | 16 | 去除强转,增强可读性 |
record 类 | 384 | 16 | 快速定义不可变数据类 |
| 密封类 | 360 | 17 | 限制继承,提高建模安全性 |
最佳使用场景总结:
| 特性 | 实践推荐场景 | 说明 |
|---|---|---|
switch 表达式 | 状态判断、分支处理、枚举映射 | 替代复杂 if-else |
| 文本块 | sql/html/json模板、配置文件构造 | 可读性强 |
instanceof 模式匹配 | 类型分发、策略切换、事件处理 | 精简类型判断 |
record 类 | 响应对象、dto、只读配置结构体 | 最适合不可变数据 |
| 密封类 | 状态机建模、业务结果分类、事件系统 | 编译时安全的继承控制 |
写在最后
从 jdk12 到 jdk17,java 逐步摆脱了“啰嗦语言”的帽子,走上了现代化转型之路。这些语法特性使得日常开发更高效、代码更简洁,也更易于维护。
未来的 java 不再只是“企业级”稳重代名词,它正在变得更轻盈、更聪明——值得每一位开发者重新审视与拥抱。
到此这篇关于jdk17前后写法超详细对比的文章就介绍到这了,更多相关jdk17前后写法内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论