Java 17作为最新的长期支持(LTS)版本,带来了多项重要改进和新特性,进一步提升了开发者的生产力和代码的可维护性。本文将深入解析Java 17中的两个核心特性:模式匹配和密封类,并通过代码示例展示它们在实际开发中的应用。
一、模式匹配:简化条件逻辑
模式匹配是Java近年来引入的一项重要特性,它通过更简洁的语法来替代传统的instanceof
加类型转换的操作方式。
1. instanceof模式匹配
在Java 16中首次引入并在Java 17中正式确定的instanceof模式匹配,可以显著简化类型检查和转换的代码:
java
// 旧写法
if (obj instanceof String) {String s = (String) obj;System.out.println(s.length());
}// Java 17新写法
if (obj instanceof String s) {System.out.println(s.length()); // s自动转换为String类型
}
这种模式匹配语法不仅减少了样板代码,还提高了代码的可读性。变量s
的作用域仅限于if语句块内,避免了变量泄露问题。
2. switch模式匹配(预览特性)
Java 17进一步扩展了模式匹配到switch语句中(作为预览特性):
java
// 旧版switch
static String formatter(Object obj) {String formatted = "unknown";if (obj instanceof Integer i) {formatted = String.format("int %d", i);} else if (obj instanceof Long l) {formatted = String.format("long %d", l);} else if (obj instanceof Double d) {formatted = String.format("double %f", d);} else if (obj instanceof String s) {formatted = String.format("String %s", s);}return formatted;
}// Java 17 switch模式匹配
static String formatterPatternSwitch(Object obj) {return switch (obj) {case Integer i -> String.format("int %d", i);case Long l -> String.format("long %d", l);case Double d -> String.format("double %f", d);case String s -> String.format("String %s", s);default -> "unknown";};
}
switch模式匹配使代码更加简洁直观,减少了重复的类型检查和转换代码。
二、密封类:精细化控制继承
密封类是Java 17中另一个重要特性,它允许类或接口的作者明确控制哪些其他类或接口可以扩展或实现它们。
1. 密封类基础
密封类通过sealed
关键字声明,并使用permits
子句指定允许的子类:
java
public sealed abstract class Shape permits Circle, Rectangle, Square {public abstract double area();
}final class Circle extends Shape {private final double radius;public Circle(double radius) {this.radius = radius;}@Overridepublic double area() {return Math.PI * radius * radius;}
}non-sealed class Rectangle extends Shape {private final double length, width;public Rectangle(double length, double width) {this.length = length;this.width = width;}@Overridepublic double area() {return length * width;}
}final class Square extends Rectangle {public Square(double side) {super(side, side);}
}
在这个例子中:
Shape
是一个密封类,只允许Circle
、Rectangle
和Square
继承它Circle
和Square
是final类,不能再被继承Rectangle
是non-sealed类,可以被任意继承
2. 密封类与模式匹配的结合
密封类与模式匹配结合使用时尤其强大,可以实现完备的模式检查:
java
public static double calculateArea(Shape shape) {return switch (shape) {case Circle c -> c.area();case Rectangle r -> r.area();case Square s -> s.area();// 不需要default分支,因为Shape是密封类且所有子类都已处理};
}
编译器可以验证switch是否覆盖了所有可能的Shape子类,如果遗漏了某个子类,编译器会报错,这大大增强了代码的安全性。
三、实际应用示例
下面我们通过一个更完整的例子展示这些特性如何协同工作:
java
sealed interface Expr permits ConstantExpr, PlusExpr, TimesExpr, NegExpr {}record ConstantExpr(int i) implements Expr {}
record PlusExpr(Expr a, Expr b) implements Expr {}
record TimesExpr(Expr a, Expr b) implements Expr {}
record NegExpr(Expr e) implements Expr {}public class Evaluator {public static int evaluate(Expr expr) {return switch (expr) {case ConstantExpr c -> c.i();case PlusExpr p -> evaluate(p.a()) + evaluate(p.b());case TimesExpr t -> evaluate(t.a()) * evaluate(t.b());case NegExpr n -> -evaluate(n.e());};}public static void main(String[] args) {Expr expr = new PlusExpr(new TimesExpr(new ConstantExpr(2), new ConstantExpr(3)),new NegExpr(new ConstantExpr(4)));System.out.println(evaluate(expr)); // 输出: 2}
}
这个例子展示了如何使用密封类和模式匹配来实现一个简单的表达式求值器。编译器可以确保我们处理了所有可能的表达式类型,大大减少了运行时错误的可能性。
四、
Java 17的模式匹配和密封类特性为Java语言带来了显著的改进:
- 模式匹配通过简化类型检查和转换的语法,减少了样板代码,提高了代码的可读性和安全性。
- 密封类提供了对类继承关系的精确控制,与模式匹配结合使用时,可以实现完备的编译时检查。
- 这些特性特别适合领域建模和实现代数数据类型(ADT),使Java在保持向后兼容的同时,也能提供更现代化的编程体验。
随着Java语言的持续演进,模式匹配和密封类将会成为Java开发者工具箱中的重要组成部分,帮助开发者编写更简洁、更安全、更易维护的代码。对于新项目,如果使用Java 17或更高版本,强烈建议考虑采用这些新特性来提升代码质量。