JDK17 前后写法对比:差点没认出是 Java!
Java精选面试题(微信小程序):5000+道面试题和选择题,真实面经,简历模版,包含Java基础、并发、JVM、线程、MQ系列、Redis、Spring系列、Elasticsearch、Docker、K8s、Flink、Spark、架构设计、大厂真题等,在线随时刷题!
Java,一直被开发者戏称为“啰嗦”,但从 JDK 12 到 JDK 17,这门语言发生了显著变化。多个语法层面的增强让 Java 更加简洁、表达力更强,也更接近现代语言的风格。本文将带你梳理这六个版本中 Java 的关键语法演进。
语法新特性一览
1. switch 表达式:不再“陷阱重重”
痛点
传统 switch 不支持返回值,且 break 的遗漏常导致 bug。
新特性(JEP 325/354/361)
-
switch可作为表达式返回值 -
引入箭头语法(
->) -
支持多标签匹配
-
使用
yield显式返回值
示例
对 HTTP 状态码进行分类处理,例如:构建统一响应消息或记录错误日志。
String result = switch (statusCode) {
case200 -> "OK";
case404 -> "Not Found";
case500 -> {
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时绑定变量
示例
处理请求参数、事件派发、策略模式中类型判断。
publicvoidprocess(Object input){
if (input instanceof String s) {
handleText(s);
} elseif (input instanceof Integer i) {
handleNumber(i);
} else {
thrownew 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 interfacePaymentResultpermitsSuccess, Failure{}
publicfinalclassSuccessimplementsPaymentResult{
String transactionId;
// ...
}
publicfinalclassFailureimplementsPaymentResult{
String reason;
// ...
}
处理支付结果:
voidhandle(PaymentResult result){
if (result instanceof Success s) {
log("Success: " + s.transactionId());
} elseif (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 interfaceOrderResultpermitsOrderSuccess, OrderFailure{}
publicfinalclassOrderSuccessimplementsOrderResult{
publicfinal String orderNo;
publicOrderSuccess(String orderNo){
this.orderNo = orderNo;
}
}
publicfinalclassOrderFailureimplementsOrderResult{
publicfinal String reason;
publicOrderFailure(String reason){
this.reason = reason;
}
}
在 Service 中处理结果:
public OrderResponse handleResult(OrderResult result){
if (result instanceof OrderSuccess success) {
returnnew OrderResponse(success.orderNo, "下单成功", 200);
} elseif (result instanceof OrderFailure failure) {
returnnew OrderResponse(null, failure.reason, 500);
}
thrownew IllegalStateException("未知结果类型");
}
优点:
-
明确约束返回类型;
-
避免非法实现或扩展;
-
结合
instanceof 模式匹配,写法简洁明了。
3. 使用 switch 表达式处理支付类型
文件:PaymentType.java(枚举)
publicenum PaymentType {
CREDIT_CARD, WECHAT, ALIPAY
}
在 Service 层选择支付服务:
public PaymentService getPaymentService(PaymentType type){
returnswitch (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")
publicclassOrderController{
@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);
}
}
总结

总结一览表
新特性总结:

最佳使用场景总结:

写在最后
从 JDK12 到 JDK17,Java 逐步摆脱了“啰嗦语言”的帽子,走上了现代化转型之路。这些语法特性使得日常开发更高效、代码更简洁,也更易于维护。
未来的 Java 不再只是“企业级”稳重代名词,它正在变得更轻盈、更聪明——值得每一位开发者重新审视与拥抱。
来源:https://juejin.cn/post/7531524096649379892
公众号“Java精选”所发表内容注明来源的,版权归原出处所有(无法查证版权的或者未注明出处的均来自网络,系转载,转载的目的在于传递更多信息,版权属于原作者。如有侵权,请联系,笔者会第一时间删除处理! 最近有很多人问,有没有读者交流群!加入方式很简单,公众号Java精选,回复“加群”,即可入群! 点击“阅读原文”,了解更多精彩内容!文章有帮助的话,点在看,转发吧!
更多推荐
所有评论(0)