1. 简介
Java 15 于 2020 年 9 月正式发布,是 JDK 平台的下一个短期版本。它在之前版本的基础上进行了一些增强,并引入了多个新特性。
本文将重点介绍 Java 15 的一些关键新特性,以及对开发者有实际意义的其他变化。
2. Records(JEP 384)
Record 是 Java 中一种新的类类型,专门用于创建不可变的数据对象。
Record 最早在 Java 14 中以早期预览的形式引入,Java 15 则进一步优化了其设计,为成为正式特性做准备。
我们先来看一个没有 Record 的传统写法,再看看 Record 是如何简化它的。
2.1. 传统写法(无 Record)
在 Record 出现之前,我们通常这样定义一个不可变的数据传输对象(DTO):
public class Person {
private final String name;
private final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
可以看到,为了创建一个简单的不可变对象,我们需要写大量的样板代码:字段必须用 final
修饰,定义全参构造器,为每个字段写 getter 方法。有时候还会加上 final
防止被继承,甚至重写 toString
、equals
和 hashCode
方法。
2.2. 使用 Record
使用 Record,我们可以将上面的类简化为:
public record Person(String name, int age) {
}
这个写法有几个关键点:
- 类定义语法是专门为 Record 设计的;
- 编译器会自动推断字段并生成构造器、getter、
toString
、equals
和hashCode
方法; - 不需要手动编写这些样板代码。
当然,Record 也支持我们自定义行为,比如添加校验逻辑:
public record Person(String name, int age) {
public Person {
if (age < 0) {
throw new IllegalArgumentException("年龄不能为负数");
}
}
}
⚠️ 注意:Record 类是 final
的,不能被继承或声明为 abstract
,也不能包含 native
方法。
3. Sealed Classes(JEP 360)
Java 之前对继承的控制粒度较粗,只有 public
、protected
、private
和包私有等修饰符。
Sealed Classes 的目标是让类或接口显式声明哪些类可以作为其子类或实现类,从而实现更细粒度的控制。
它引入了两个新关键字:sealed
和 permits
:
public abstract sealed class Person
permits Employee, Manager {
//...
}
在这个例子中,Person
类只允许 Employee
和 Manager
作为其子类:
public final class Employee extends Person {
}
public non-sealed class Manager extends Person {
}
✅ 任何继承 sealed 类的类必须声明为 sealed
、non-sealed
或 final
,确保类层次结构是有限且可预测的。
这种有限的类结构对模式匹配(Pattern Matching)非常有帮助:
if (person instanceof Employee) {
return ((Employee) person).getEmployeeId();
}
else if (person instanceof Manager) {
return ((Manager) person).getSupervisorId();
}
没有 Sealed Class 的情况下,编译器无法确定是否覆盖了所有子类,容易导致遗漏。
4. Hidden Classes(JEP 371)
Hidden Classes 是 Java 15 引入的一个新特性,主要用于运行时动态生成不可发现的类。
这类类不能被其他类链接,也无法通过反射获取,通常生命周期较短,设计上也更注重加载和卸载效率。
虽然大多数开发者用不到,但对于 JVM 语言或动态字节码操作的场景,Hidden Classes 提供了更安全、更高效的选择。
⚠️ Java 之前的匿名类虽然功能类似,但依赖于 Unsafe
API,而 Hidden Classes 不需要。
5. Pattern Matching for instanceof(JEP 375)
Pattern Matching for instanceof 是 Java 14 引入的预览特性,Java 15 继续保持预览状态,未新增功能。
它的目的是简化 instanceof + 强转的样板代码:
传统写法:
if (person instanceof Employee) {
Employee employee = (Employee) person;
Date hireDate = employee.getHireDate();
//...
}
使用 Pattern Matching 后:
if (person instanceof Employee employee) {
Date hireDate = employee.getHireDate();
//...
}
变量 employee
会在类型检查成功后自动赋值,无需手动强转。
还可以与条件表达式结合使用:
if (person instanceof Employee employee && employee.getYearsOfService() > 5) {
//...
}
未来版本中,该特性有望扩展到 switch
等更多语法结构中。
6. Foreign Memory Access API(JEP 383)
Foreign Memory Access API 是 Java 14 的孵化特性,Java 15 继续孵化并新增了以下功能:
- 新增
VarHandle
API,支持自定义内存访问; - 支持通过
Spliterator
接口并行处理内存段; - 增强对
mapped
内存段的支持; - 可处理来自本地调用的地址。
Foreign Memory 指的是 JVM 堆外内存,不受 GC 管理,适合处理大块数据,比如缓存、内存映射文件等。
✅ 虽然普通开发者很少直接使用,但对第三方库(如 Netty、Chronicle 等)来说意义重大。
7. 垃圾收集器更新
Java 15 中,ZGC(JEP 377)和 Shenandoah(JEP 379)不再是实验性特性,正式支持使用。
- 默认 GC 依然是 G1;
- ZGC 和 Shenandoah 可通过参数启用;
- Oracle JDK 不包含 Shenandoah,需使用 OpenJDK 或其他厂商版本。
8. 其他重要变化
- ✅ Text Blocks(文本块)在 Java 15 正式支持,告别字符串拼接的痛苦;
- ✅ Helpful NullPointerExceptions(增强空指针提示)默认启用,错误定位更清晰;
- ⚠️ DatagramSocket API 重写,为 Project Loom 做准备;
- ✅ 新增对 EdDSA(爱德华曲线数字签名算法) 的支持;
- ❌ Nashorn JavaScript 引擎被移除,GraalVM 成为主流;
- ❌ Biased Locking、Solaris/SPARC 端口、RMI Activation 被弃用或移除。
9. 总结
Java 15 在继承前几版的基础上,带来了 Record、Sealed Classes、Hidden Classes 等新特性,同时将 ZGC、Shenandoah 等 GC 正式化。
⚠️ Java 15 是短期版本,支持将于 2021 年 3 月结束。之后将迎来 Java 16,再之后就是 LTS 版本 Java 17。
对于有经验的开发者来说,Java 15 是一个值得关注的过渡版本,尤其在语言现代化方面迈出了一大步。