Java 14 新特性详解与实践
Java 14 于 2020年3月17日正式发布,是一个非LTS版本。本文档将详细介绍 Java 14 中引入的主要新特性和改进。
语言特性
1. Switch 表达式 (正式版本)
Switch 表达式在 Java 12 和 13 中作为预览特性存在,在 Java 14 中正式成为标准特性。
基本语法
arduino
// 传统 switch 语句
String result;
switch (day) {
case MONDAY:
case FRIDAY:
case SUNDAY:
result = "Meh";
break;
case TUESDAY:
result = "Tiring";
break;
case THURSDAY:
case SATURDAY:
result = "Nice";
break;
case WEDNESDAY:
result = "Hump day";
break;
default:
throw new IllegalStateException("Invalid day: " + day);
}
// 新的 switch 表达式
String result = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> "Meh";
case TUESDAY -> "Tiring";
case THURSDAY, SATURDAY -> "Nice";
case WEDNESDAY -> "Hump day";
};
yield 关键字
csharp
String result = switch (day) {
case MONDAY -> {
System.out.println("Monday blues");
yield "Meh";
}
case TUESDAY -> {
System.out.println("Tuesday troubles");
yield "Tiring";
}
default -> "Other day";
};
2. 有用的 NullPointerException
增强了 NullPointerException 的错误信息,精确指出哪个变量为 null。
示例
typescript
public class HelpfulNPE {
static class Person {
String name;
Address address;
}
static class Address {
String city;
}
public static void main(String[] args) {
Person person = new Person();
// 这将抛出更详细的 NPE 信息
String city = person.address.city;
}
}
错误信息变化:
php
// Java 13 及之前
Exception in thread "main" java.lang.NullPointerException
at HelpfulNPE.main(HelpfulNPE.java:15)
// Java 14
Exception in thread "main" java.lang.NullPointerException:
Cannot read field "city" because "person.address" is null
at HelpfulNPE.main(HelpfulNPE.java:15)
3. 记录类型 (预览特性)
Records 是一种新的类声明形式,用于创建不可变的数据载体类。
基本语法
arduino
// 传统方式
public class PersonOld {
private final String name;
private final int age;
public PersonOld(String name, int age) {
this.name = name;
this.age = age;
}
public String name() { return name; }
public int age() { return age; }
@Override
public boolean equals(Object o) {
// 标准 equals 实现
}
@Override
public int hashCode() {
// 标准 hashCode 实现
}
@Override
public String toString() {
// 标准 toString 实现
}
}
// 使用 Record
public record Person(String name, int age) {}
Record 特性
csharp
public record Point(int x, int y) {
// 紧凑构造器
public Point {
if (x < 0 || y < 0) {
throw new IllegalArgumentException("坐标不能为负数");
}
}
// 静态方法
public static Point origin() {
return new Point(0, 0);
}
// 实例方法
public double distanceFromOrigin() {
return Math.sqrt(x * x + y * y);
}
}
// 使用示例
Point p1 = new Point(3, 4);
Point p2 = new Point(3, 4);
System.out.println(p1.x()); // 3
System.out.println(p1.y()); // 4
System.out.println(p1.equals(p2)); // true
System.out.println(p1.toString()); // Point[x=3, y=4]
System.out.println(p1.distanceFromOrigin()); // 5.0
4. 模式匹配 instanceof (预览特性)
简化了 instanceof 检查后的类型转换。
传统方式 vs 新方式
typescript
// 传统方式
if (obj instanceof String) {
String str = (String) obj;
System.out.println(str.length());
}
// 模式匹配 instanceof
if (obj instanceof String str) {
System.out.println(str.length());
}
// 更复杂的示例
public String formatValue(Object obj) {
if (obj instanceof Integer i) {
return String.format("整数: %d", i);
} else if (obj instanceof String s && s.length() > 10) {
return String.format("长字符串: %s", s.substring(0, 10) + "...");
} else if (obj instanceof String s) {
return String.format("字符串: %s", s);
} else {
return "未知类型";
}
}
1. String API 增强
1.1 新增方法
ini
// String.formatted() - 格式化字符串
String name = "Java";
int version = 14;
String message = "Hello, %s %d!".formatted(name, version);
System.out.println(message); // Hello, Java 14!
// String.stripIndent() - 移除缩进
String multiline = """
第一行
第二行
第三行
""";
String stripped = multiline.stripIndent();
System.out.println(stripped);
/*
第一行
第二行
第三行
*/
// String.translateEscapes() - 转义字符处理
String escaped = "Hello\nWorld\t!";
String translated = escaped.translateEscapes();
System.out.println(translated); // Hello[换行]World[制表符]!
最佳实践
1.1 Switch 表达式
typescript
// 好的实践
public String processStatus(Status status) {
return switch (status) {
case PENDING -> "处理中";
case APPROVED -> "已批准";
case REJECTED -> "已拒绝";
case CANCELLED -> "已取消";
}; // 编译器确保所有情况都被覆盖
}
// 避免混用新旧语法
public String processStatusBad(Status status) {
switch (status) {
case PENDING -> "处理中"; // 新语法
case APPROVED: // 旧语法,不推荐混用
return "已批准";
default -> "未知状态";
}
}
1.2 Record 使用
csharp
// 好的实践 - 不可变数据载体
public record Person(String name, int age) {
public Person {
if (age < 0) throw new IllegalArgumentException("年龄不能为负数");
if (name == null || name.trim().isEmpty()) {
throw new IllegalArgumentException("姓名不能为空");
}
}
}
// 避免 - 复杂业务逻辑类
// Record 不适合包含大量业务逻辑的类
1.3 模式匹配 instanceof
typescript
// 好的实践
public double calculateArea(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("未知形状");
}
// 避免过于复杂的条件
public String formatComplexCondition(Object obj) {
// 避免这样的复杂条件,考虑重构
if (obj instanceof String s && s.length() > 10 && s.contains("important") && !s.startsWith("test")) {
return "复杂字符串处理";
}
return "简单处理";
}
总结
Java 14 虽然是一个非 LTS 版本,但引入了多个重要特性:
正式特性
- Switch 表达式 - 提供了更简洁、安全的分支处理方式
- 有用的 NullPointerException - 极大改善了调试体验
预览特性
- Record 类型 - 简化不可变数据类的创建
- 模式匹配 instanceof - 减少样板代码