Java 17+ 新特性实战
Java 17 是 LTS 版本,带来了 record、sealed class、switch 模式匹配等一大批改变写法的特性。本文用实战例子讲清这些新特性怎么用、什么时候用。
一、record:数据类一行搞定
以前写一个纯数据类要写一堆 getter、setter、equals、hashCode、toString。record 一行搞定:
// 以前:要写 100 行的 POJO
public class User {
private final Long id;
private final String name;
private final String email;
// 构造器、getter、equals、hashCode、toString 全部手写
}
// 现在:一行 record
public record User(Long id, String name, String email) {}
// 自动生成:构造器、字段访问器、equals、hashCode、toString
User u = new User(1L, "小明", "xm@example.com");
System.out.println(u.name()); // 访问器方法(不是 getName())
System.out.println(u);
// User[id=1, name=小明, email=xm@example.com]
注意:record 是 final 的,不能继承其他类。字段是 final 的。适合 DTO、值对象、数据载体。不适合需要继承或可变状态的实体。
二、sealed class:限制继承层级
以前 Java 的类要么可以随便被继承(默认),要么不能被继承(final)。sealed 在中间:明确列出允许哪些子类继承。
// 密封类:只允许 Circle、Rectangle、Triangle 继承
public sealed interface Shape
permits Circle, Rectangle, Triangle {}
public record Circle(double radius) implements Shape {}
public record Rectangle(double width, double height) implements Shape {}
public record Triangle(double base, double height) implements Shape {}
// 不允许其他类继承 Shape,编译器会报错
sealed 配合 switch 模式匹配,编译器可以帮你检查是否覆盖了所有子类。
三、switch 模式匹配
以前的 switch 只能匹配常量。现在 switch 可以匹配类型、解构 record、加条件判断。
// 以前:instanceof 加类型强转,啰嗦
public static double area(Shape shape) {
if (shape instanceof Circle c) {
return Math.PI * c.radius() * c.radius();
} else if (shape instanceof Rectangle r) {
return r.width() * r.height();
} else if (shape instanceof Triangle t) {
return 0.5 * t.base() * t.height();
}
throw new IllegalArgumentException();
}
// 现在:switch 模式匹配,简洁优雅
public static double area(Shape shape) {
return switch (shape) {
case Circle c -> Math.PI * c.radius() * c.radius();
case Rectangle r -> r.width() * r.height();
case Triangle t -> 0.5 * t.base() * t.height();
// sealed 保证穷尽,不需要 default
};
}
四、模式匹配的进阶用法
// 带条件的模式匹配
public static String classify(Number num) {
return switch (num) {
case Integer i when i > 0 -> "正整数";
case Integer i when i < 0 -> "负整数";
case Integer i -> "零";
case Double d when d > 0 -> "正小数";
case null -> "空值";
default -> "其他数字";
};
}
// record 解构
record Point(int x, int y) {}
record Line(Point start, Point end) {}
public static void printLine(Line line) {
if (line instanceof Line(Point(var x1, var y1), Point(var x2, var y2))) {
System.out.printf("从(%d,%d)到(%d,%d)%n", x1, y1, x2, y2);
}
}
五、其他实用新特性
// Text Blocks(文本块):多行字符串不用拼接
String json = """
{
"name": "小明",
"age": 25
}
""";
// var 类型推断(局部变量)
var list = new ArrayList<String>();
var map = new HashMap<String, Object>();
// instanceof 模式匹配
if (obj instanceof String s && s.length() > 5) {
System.out.println(s.toUpperCase());
}
六、什么时候用这些新特性
| 特性 | 使用场景 |
|---|---|
| record | DTO、值对象、数据载体 |
| sealed | 领域模型有明确子类层级时 |
| switch 模式匹配 | 多类型分支逻辑替代 if-else 链 |
| Text Blocks | JSON、SQL、HTML 多行字符串 |
| var | 局部变量类型明显时(如 new HashMap<String, Object>()) |
七、总结
Java 17+ 的新特性不是锦上添花,而是让 Java 代码更简洁、更安全。record 消灭了 POJO 样板代码,sealed 让领域模型层级更可控,switch 模式匹配替代了啰嗦的 if-else 链。新项目直接用 Java 17+,老项目逐步迁移这些特性。