JDK17 前后写法对比:差点没认出是 Java!

Java,一直被开发者戏称为"啰嗦",但从 JDK 12 到 JDK 17,这门语言发生了显著变化。多个语法层面的增强让 Java 更加简洁、表达力更强,也更接近现代语言的风格。本文将带你梳理这六个版本中 Java 的关键语法演进。

语法新特性一览

1. switch 表达式:不再"陷阱重重"

痛点

传统 switch 不支持返回值,且 break 的遗漏常导致 bug。

新特性(JEP 325/354/361)

  • switch 可作为表达式返回值
  • 引入箭头语法(->)
  • 支持多标签匹配
  • 使用 yield 显式返回值

示例

对 HTTP 状态码进行分类处理,例如:构建统一响应消息或记录错误日志。

rust 复制代码
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 查询

ini 复制代码
String query = """  
    SELECT id, name, email  
    FROM users  
    WHERE status = 'ACTIVE'  
    ORDER BY created_at DESC  
    """;

示例2 - html 模板

ini 复制代码
String html = """  
    <html>  
        <body>  
            <h1>Welcome, %s!</h1>  
        </body>  
    </html>  
    """.formatted(user.getName());

优势:更易编写 JSON、SQL、HTML 等嵌入式文本内容。

3. instanceof 模式匹配:更聪明的类型判断

痛点

类型判断后必须显式强转,重复又冗余。

新特性(JEP 305,JDK 16):

  • 支持 instanceof 时绑定变量

示例

处理请求参数、事件派发、策略模式中类型判断。

scss 复制代码
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 - 接口响应

csharp 复制代码
public record ApiResponse<T>(int code, String message, T data) {}  
  
ApiResponse<User> response = new ApiResponse<>(200, "OK", user);

示例2 - 封装查询结果

arduino 复制代码
public record UserSummary(String name, int postCount){}  
  
List<UserSummary> summaries = userRepository.getSummaries();

优势:专为数据建模而生,简洁且不易出错。

5. 密封类(Sealed Classes):限制继承范围

痛点

接口或抽象类可以被任意扩展,无法控制子类范围。

新特性(JEP 360,JDK 17)

  • 使用 sealed 修饰类/接口
  • 显式声明允许继承的子类(使用 permits)

示例

用于建模流程状态、支付状态、登录结果、事件分发等,确保所有子类都是受控的。

支付状态

arduino 复制代码
public sealed interfacePaymentResultpermitsSuccess, Failure{}  

publicfinalclassSuccessimplementsPaymentResult{  
    String transactionId;  
    // ...  
}  

publicfinalclassFailureimplementsPaymentResult{  
    String reason;  
    // ...  
}

处理支付结果:

scss 复制代码
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

vbnet 复制代码
public record OrderRequest(Long userId, List<Long> productIds, String paymentType){}

文件:OrderResponse.java

arduino 复制代码
public record OrderResponse(String orderNo, String message, int code){}

用途:

  • 在 Controller** 层接收请求/返回响应;
  • 省略 getter/setter/构造器;
  • 天然不可变,适合并发和函数式风格。

2. 使用 sealed + instanceof 进行订单结果建模和处理

文件:OrderResult.java

typescript 复制代码
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 中处理结果:

java 复制代码
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(枚举)

rust 复制代码
publicenum PaymentType {  
    CREDIT_CARD, WECHAT, ALIPAY  
}

在 Service 层选择支付服务:

typescript 复制代码
public PaymentService getPaymentService(PaymentType type){  
    returnswitch (type) {  
        case CREDIT_CARD -> creditCardService;  
        case WECHAT -> wechatPayService;  
        case ALIPAY -> aliPayService;  
    };  
}

优点:

  • 替代 if-else,代码更整洁;
  • 编译器检查是否遗漏分支。

4. 使用文本块生成 SQL 或消息模板

在 Repository 中写动态 SQL:

ini 复制代码
String sql = """  
    SELECT * FROM orders  
    WHERE user_id = ?  
    AND created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY)  
    ORDER BY created_at DESC  
    """;

发送邮件或通知模板:

ini 复制代码
String content = """  
    亲爱的用户,您的订单已成功创建:  
    订单编号:%s  
    总金额:%.2f 元  
    感谢您的购买!  
    """.formatted(orderNo, totalAmount);

优点:

  • 无需拼接;
  • 保持结构清晰,适合业务模板开发。

5. Controller 层综合调用示例

less 复制代码
@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);  
    }  
}

总结

特性 实际作用 模块
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、只读配置结构体 最适合不可变数据
密封类 状态机建模、业务结果分类、事件系统 编译时安全的继承控制

写在最后

从 JDK 12 到 JDK 17,Java 逐步摆脱了"啰嗦语言"的帽子,走上了现代化转型之路。这些语法特性使得日常开发更高效、代码更简洁,也更易于维护。

未来的 Java 不再只是"企业级"稳重代名词,它正在变得更轻盈、更聪明------值得每一位开发者重新审视与拥抱。

相关推荐
金銀銅鐵8 小时前
[Java] 用 GUI 展示 EnumSet 增减元素时的内部变化(上)
java·后端·ai编程
念何架构之路9 小时前
go-grpc设计思想
开发语言·后端·golang
system_error_x9 小时前
SpringBoot 集成 Thymeleaf 简洁入门
java·spring boot·后端
步行cgn11 小时前
Spring MVC 视图机制的核心接口与类
java·开发语言·后端·spring·mvc
码事漫谈12 小时前
AI 读你的提示词,其实很没耐心
后端
用户83562907805113 小时前
如何使用 Python 格式化 Excel 单元格中的长文本
后端·python
我命由我1234513 小时前
Python 开发 - Python 的 pathlib
java·开发语言·后端·python·学习·java-ee·学习方法
IT_陈寒13 小时前
Java性能优化完全指南
前端·人工智能·后端
电子IT笔记13 小时前
对接群晖NAS,上传和删除踩坑记录
前端·后端
Mk5987813 小时前
P4:把 Agent 的记忆搬进 Redis —— AgentScope-Java 工程化实战
后端