Java 16 正式Records
2026/1/15大约 3 分钟JavaJava版本特性RecordsJavaJava新特性LambdaStreamOptional模块化虚拟线程
概述
Java 16(2021年3月)将多个预览特性正式发布,包括 Records 和 instanceof 模式匹配。
Records (正式)
// 正式成为标准特性
public record Point(int x, int y) {}
public record Person(String name, int age) {
// 紧凑构造器
public Person {
Objects.requireNonNull(name);
if (age < 0) throw new IllegalArgumentException();
}
// 静态工厂方法
public static Person of(String name, int age) {
return new Person(name, age);
}
}
// 本地 Record
void process(List<String> items) {
record Item(String name, int count) {}
var grouped = items.stream()
.collect(Collectors.groupingBy(
s -> s,
Collectors.counting()
))
.entrySet().stream()
.map(e -> new Item(e.getKey(), e.getValue().intValue()))
.toList();
}instanceof 模式匹配 (正式)
// 正式成为标准特性
public void process(Object obj) {
if (obj instanceof String s) {
System.out.println(s.toUpperCase());
} else if (obj instanceof Integer i) {
System.out.println(i * 2);
} else if (obj instanceof List<?> list && !list.isEmpty()) {
System.out.println("List size: " + list.size());
}
}
// 在 equals 方法中使用
@Override
public boolean equals(Object obj) {
return obj instanceof Point p
&& this.x == p.x
&& this.y == p.y;
}Stream.toList()
// Java 16 之前
List<String> list = stream.collect(Collectors.toList());
// Java 16 之后
List<String> list = stream.toList();
// 注意:返回的是不可变列表
List<String> names = Stream.of("Alice", "Bob", "Charlie")
.filter(s -> s.length() > 3)
.toList();
// names.add("David"); // 抛出 UnsupportedOperationException日期时间增强
Day Period
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("B");
LocalTime morning = LocalTime.of(9, 0);
LocalTime afternoon = LocalTime.of(14, 0);
LocalTime evening = LocalTime.of(20, 0);
System.out.println(morning.format(formatter)); // "in the morning"
System.out.println(afternoon.format(formatter)); // "in the afternoon"
System.out.println(evening.format(formatter)); // "in the evening"
// 中文
DateTimeFormatter cnFormatter = DateTimeFormatter.ofPattern("B", Locale.CHINA);
System.out.println(morning.format(cnFormatter)); // "上午"Vector API (孵化)
用于 SIMD(单指令多数据)操作的 API。
// 需要添加模块
// --add-modules jdk.incubator.vector
import jdk.incubator.vector.*;
static final VectorSpecies<Float> SPECIES = FloatVector.SPECIES_256;
void vectorAdd(float[] a, float[] b, float[] c) {
int i = 0;
int upperBound = SPECIES.loopBound(a.length);
for (; i < upperBound; i += SPECIES.length()) {
var va = FloatVector.fromArray(SPECIES, a, i);
var vb = FloatVector.fromArray(SPECIES, b, i);
var vc = va.add(vb);
vc.intoArray(c, i);
}
// 处理剩余元素
for (; i < a.length; i++) {
c[i] = a[i] + b[i];
}
}密封类 (第二次预览)
public sealed interface Shape
permits Circle, Rectangle, Triangle {
double area();
}
public record Circle(double radius) implements Shape {
public double area() {
return Math.PI * radius * radius;
}
}
public record Rectangle(double width, double height) implements Shape {
public double area() {
return width * height;
}
}
public final class Triangle implements Shape {
private final double base, height;
public Triangle(double base, double height) {
this.base = base;
this.height = height;
}
public double area() {
return 0.5 * base * height;
}
}Unix-Domain Socket Channels
支持 Unix 域套接字。
// 服务端
UnixDomainSocketAddress address = UnixDomainSocketAddress.of("/tmp/socket");
ServerSocketChannel server = ServerSocketChannel.open(StandardProtocolFamily.UNIX);
server.bind(address);
SocketChannel client = server.accept();
ByteBuffer buffer = ByteBuffer.allocate(1024);
client.read(buffer);
// 客户端
SocketChannel channel = SocketChannel.open(StandardProtocolFamily.UNIX);
channel.connect(UnixDomainSocketAddress.of("/tmp/socket"));
channel.write(ByteBuffer.wrap("Hello".getBytes()));外部链接器 API (孵化)
用于调用本地代码的 API,替代 JNI。
// 需要添加模块
// --add-modules jdk.incubator.foreign
import jdk.incubator.foreign.*;
// 调用 C 库函数
CLinker linker = CLinker.getInstance();
MethodHandle strlen = linker.downcallHandle(
CLinker.systemLookup().lookup("strlen").get(),
MethodType.methodType(long.class, MemoryAddress.class),
FunctionDescriptor.of(CLinker.C_LONG, CLinker.C_POINTER)
);
try (MemorySegment str = CLinker.toCString("Hello")) {
long len = (long) strlen.invoke(str.address());
System.out.println("Length: " + len); // 5
}打包工具 jpackage
创建平台特定的安装包。
# 创建 Windows 安装程序
jpackage --name MyApp --input lib --main-jar myapp.jar \
--main-class com.example.Main --type msi
# 创建 macOS 应用
jpackage --name MyApp --input lib --main-jar myapp.jar \
--main-class com.example.Main --type dmg
# 创建 Linux 包
jpackage --name MyApp --input lib --main-jar myapp.jar \
--main-class com.example.Main --type deb其他改进
默认强封装 JDK 内部
# 访问内部 API 需要显式开放
java --add-opens java.base/java.lang=ALL-UNNAMED MyAppZGC 并发线程栈处理
减少 GC 停顿时间。
弹性元空间
更高效的元空间内存管理。
总结
| 特性 | 说明 |
|---|---|
| Records | 正式发布,不可变数据类 |
| instanceof 模式匹配 | 正式发布,简化类型检查 |
| Stream.toList() | 便捷方法,返回不可变列表 |
| Vector API | SIMD 操作(孵化) |
| Unix-Domain Socket | 支持 Unix 域套接字 |
| jpackage | 创建平台安装包 |
Java 16 是一个重要的里程碑,Records 和 instanceof 模式匹配的正式发布为 Java 带来了更现代的编程体验。
