好的,我们来详细解析 Java 17 及之后引入的一些重要新特性。Java 17 是一个长期支持版本,包含了许多增强语言表达力、开发效率和性能的特性。
1. 密封类 (Sealed Classes - JEP 409)
-
目的: 限制哪些类或接口可以继承或实现它们,提供了更精细的继承控制。
-
语法: 使用
sealed修饰符声明类或接口,并使用permits子句明确指定允许的子类。javapublic sealed class Shape permits Circle, Square, Rectangle { // ... } public final class Circle extends Shape { /* ... */ } public final class Square extends Shape { /* ... */ } public final class Rectangle extends Shape { /* ... */ } -
关键点:
- 允许的子类必须是
final,sealed, 或non-sealed。 non-sealed类可以打破密封性,允许任意扩展。- 增强了模式匹配(见下文)的能力。
- 提高了代码的安全性和可维护性。
- 允许的子类必须是
2. 模式匹配的增强
a. switch 的模式匹配 (JEP 406 - 预览于 17, JEP 420 - 二次预览于 18, JEP 427 - 三次预览于 19, 最终定案于 JEP 433 - Java 20)
- 目的: 简化基于类型和结构的条件分支代码。
- 特性:
-
类型匹配模式: 在
case标签中直接匹配类型并绑定变量。javaObject obj = ...; switch (obj) { case String s -> System.out.println("String: " + s); case Integer i -> System.out.println("Integer: " + i); case null -> System.out.println("Null!"); default -> System.out.println("Other"); } -
守卫条件 (Guard): 在模式后使用
when添加额外的布尔条件。javaswitch (obj) { case String s when s.length() > 5 -> System.out.println("Long string"); case String s -> System.out.println("Short string"); // ... } -
模式匹配记录 (Record Patterns - JEP 405 - 预览于 19, JEP 432 - 二次预览于 20, JEP 440 - Java 21):
javarecord Point(int x, int y) {} Point p = new Point(3, 4); if (p instanceof Point(int x, int y)) { // 解构记录 System.out.println(x + ", " + y); } -
模式匹配 null: 显式处理
null情况。
-
b. instanceof 的模式匹配 (JEP 394 - Java 16)
-
目的: 将类型检查和变量绑定合并为一步。
-
语法:
javaif (obj instanceof String s) { // 在这里可以直接使用变量 s,它已经被转换为 String 类型 System.out.println(s.length()); }
3. 文本块 (Text Blocks - JEP 378 - Java 15)
-
目的: 简化多行字符串字面量的书写,提高可读性。
-
语法: 使用三个双引号
"""作为定界符。javaString html = """ <html> <body> <p>Hello, World!</p> </body> </html> """; -
特点:
- 自动处理缩进(去除共同的前导空白)。
- 保留换行符。
- 可以使用
\避免行尾换行,或\s表示一个空格。
4. Record 类 (Record Classes - JEP 395 - Java 16)
-
目的: 创建不可变的数据载体类,减少样板代码。
-
语法:
javapublic record Point(int x, int y) {} -
编译器自动生成:
final类。- 所有字段 (
private final) 和对应的访问器方法 (x(),y())。 - 规范的构造函数。
equals(),hashCode(),toString()方法。
-
限制: 不能显式继承其他类(隐含继承
Record),字段不可变。
5. 外部函数和内存 API (Foreign Function & Memory API - JEP 412 - 孵化于 16, JEP 419 - 二次孵化于 17, JEP 424 - Java 19 预览, JEP 434 - Java 20 二次预览)
-
目的: 提供一套安全、高效的 API,用于替代 JNI,访问本地代码(如 C 库)和管理堆外内存。
-
核心接口:
MemorySegment,MemoryAddress,SegmentAllocator,SymbolLookup,FunctionDescriptor,Linker,MethodHandle。 -
示例 (概念性):
java// 查找 C 标准库中的 strlen 函数 Linker linker = Linker.nativeLinker(); SymbolLookup stdLib = linker.defaultLookup(); MethodHandle strlenHandle = linker.downcallHandle( stdLib.lookup("strlen").get(), FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS) ); // 分配内存并存储字符串 try (MemorySegment cString = SegmentAllocator.implicitAllocator().allocateUtf8String("Hello")) { long length = (long) strlenHandle.invoke(cString); // 调用 strlen System.out.println(length); } -
优点: 更安全(内存访问边界检查),性能更好,更符合 Java 习惯。
6. NullPointerException 增强信息 (JEP 358 - Java 14)
-
目的: 更清晰地指出
NullPointerException发生的确切原因。 -
行为: 当 JVM 抛出
NullPointerException时,消息会指出哪个变量是null。Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "someString" is null
7. Vector API (孵化器阶段)
- 目的: 表达向量计算,这些计算可以在运行时编译成支持的 CPU 架构上的最优向量指令,从而获得优于等效标量计算的性能。
- 状态: 从 Java 16 (JEP 338) 开始孵化,经历了多个孵化版本 (JEP 414, JEP 417, JEP 423),在 Java 19 (JEP 426) 进入第四轮孵化,Java 20 (JEP 438) 进入第五轮孵化。尚未转正。
- 核心类:
VectorSpecies,Vector.
8. 结构化并发 (Structured Concurrency - 孵化器阶段)
- 目的: 将多个并发任务视为一个工作单元,简化错误处理和取消操作,提高可靠性并增强可观测性。
- 状态: 最初作为 Project Loom 的一部分孵化,Java 19 (JEP 428) 作为孵化 API 引入,Java 20 (JEP 437) 进入第二轮孵化。
- 核心 API:
StructuredTaskScope.
9. 其他值得注意的特性
- 增强的伪随机数生成器 (JEP 356 - Java 17): 提供新的接口类型
RandomGenerator和工厂方法,更灵活地获取各种 PRNG 算法。 - 新的 macOS 渲染管道 (JEP 382 - Java 17): 使用 Apple Metal API 为 macOS 实现 Java 2D 渲染管道。
- 弃用 Applet API (Java 17): 标记为移除。
- 强封装 JDK 内部元素 (JEP 403 - Java 17): 默认情况下强封装 JDK 内部 API,移除
--illegal-access标志。 - 移除 RMI 激活 (JEP 398 - Java 15): 移除 RMI 激活机制。
- 基于 Unix-Domain Socket 的 Channels (JEP 380 - Java 16): 增加对 Unix-Domain Socket 的支持。
- Elastic Metaspace (JEP 387 - Java 16): 改进元空间内存管理,减少占用并提高性能。
总结
Java 17 及后续版本在语言层面(密封类、模式匹配、记录类、文本块)、并发模型(结构化并发)、本地互操作性(FFM API)和性能(Vector API)等方面都带来了显著改进。密封类和增强的模式匹配共同提升了代码的表达力和安全性。记录类和文本块减少了样板代码。FFM API 为安全高效的本地交互铺平了道路。开发者应关注这些特性,特别是 Java 17 作为 LTS 版本的重要性。