Java 14 将 Switch 表达式正式化,并引入了 Records、instanceof 模式匹配作为预览特性。
正式特性
【必备】Switch 表达式
Java 14 将 Switch 表达式转正了,让条件判断变得更简洁和安全。
在这之前,传统的 switch 语句存在不少问题,比如需要手动添加 break 防止穿透、赋值不方便等:
String dayType;
switch (day) {
case MONDAY:
case TUESDAY:
case WEDNESDAY:
case THURSDAY:
case FRIDAY:
dayType = "工作日";
break;
case SATURDAY:
case SUNDAY:
dayType = "周末";
break;
default:
dayType = "未知";
break;
}
// 赋值不方便
int score;
switch (grade) {
case 'A':
System.out.println("优秀!");
score = 90;
break;
case 'B':
score = 80;
break;
default:
score = 0;
}在 Java 14 之后,可以直接这么写:
// Java 14 的简洁写法
String dayType = switch (day) {
case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> "工作日";
case SATURDAY, SUNDAY -> "周末";
default -> "未知";
};
// 支持复杂逻辑的 yield 关键字
int score = switch (grade) {
case 'A' -> {
System.out.println("优秀!");
yield 90; // 使用 yield 返回值
}
case 'B' -> 80;
default -> 0;
};上述代码中,我们使用了 Switch 表达式增强的几个特性:
箭头语法:使用
->替代冒号,自动防止 fall-through(不用写 break 了)多标签支持:
case A, B, C ->一行处理多个条件表达式求值:可以直接使用 yield 关键字返回值并赋给变量
这样一来,多条件判断变得更优雅了!还能避免忘记 break 导致的逻辑错误。
// 实际应用示例:根据月份判断季节
String season = switch (month) {
case 12, 1, 2 -> "冬季";
case 3, 4, 5 -> "春季";
case 6, 7, 8 -> "夏季";
case 9, 10, 11 -> "秋季";
default -> throw new IllegalArgumentException("无效月份: " + month);
};【必备】有用的空指针异常
Java 14 改进了 NullPointerException 的错误信息。JVM 会提供更详细的堆栈跟踪信息,指出导致异常的具体位置和原因,让调试变得更加容易

传统的 NPE 信息往往只告诉你在哪一行出错,但不知道具体是哪个变量为 null:
// 传统的 NPE 信息
Exception in thread "main" java.lang.NullPointerException
at MyClass.method(MyClass.java:15)Java 14 的改进版本会提供更详细的信息:
// Java 14 的详细 NPE 信息
Exception in thread "main" java.lang.NullPointerException:
Cannot invoke "String.length()" because "user.getName()" is null
at MyClass.method(MyClass.java:15)这个特性需要通过 JVM 参数启用:
java -XX:+ShowCodeDetailsInExceptionMessages MyApp【了解】G1 垃圾收集器改进
G1 的 NUMA 感知内存分配
Java 14 改进了 G1 垃圾收集器,使其能够感知 NUMA(Non-Uniform Memory Access)架构:
java -XX:+UseG1GC -XX:+UseNUMA MyApp这个改进可以:
提高多 CPU 系统的内存访问效率
减少跨 NUMA 节点的内存访问
改善大型服务器的性能表现
macOS 和 Windows 上的 ZGC
Java 14 将 ZGC 扩展到 macOS 和 Windows 平台:
# macOS 上启用 ZGC
java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC MyApp
# Windows 上启用 ZGC
java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC MyApp之前 ZGC 只支持 Linux,现在跨平台支持让更多开发者可以体验低延迟 GC。
【了解】JFR 事件流
Java 14 引入了 JFR(Java Flight Recorder)事件流 API,允许实时消费 JFR 事件:
import jdk.jfr.consumer.RecordingStream;
public class JFRStreamExample {
public static void main(String[] args) {
try (RecordingStream rs = new RecordingStream()) {
// 启用 GC 事件
rs.enable("jdk.GarbageCollection");
// 设置事件处理器
rs.onEvent("jdk.GarbageCollection", event -> {
System.out.println("GC 事件: " + event.getValue("gcId"));
System.out.println("GC 时间: " + event.getDuration());
});
// 启用 CPU 负载事件
rs.enable("jdk.CPULoad").withPeriod(Duration.ofSeconds(1));
rs.onEvent("jdk.CPULoad", event -> {
double cpuLoad = event.getFloat("machineTotal");
System.out.println("CPU 负载: " + cpuLoad * 100 + "%");
});
// 开始流式处理
rs.start();
}
}
}这个 API 可以用于:
实时性能监控
自动化性能分析
构建自定义监控工具
【了解】其他正式特性
非易失性映射字节缓冲区
Java 14 支持将 MappedByteBuffer 映射到非易失性内存(NVM):
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.StandardOpenOption;
// 映射到非易失性内存
try (FileChannel channel = FileChannel.open(
Paths.get("/mnt/pmem/datafile"),
StandardOpenOption.READ,
StandardOpenOption.WRITE)) {
MappedByteBuffer buffer = channel.map(
FileChannel.MapMode.READ_WRITE, 0, channel.size());
// 数据直接持久化到 NVM
buffer.putInt(42);
buffer.force(); // 强制写入
}删除 CMS 垃圾收集器
Java 14 正式移除了 CMS(Concurrent Mark Sweep)垃圾收集器:
# 这个参数在 Java 14 中不再有效
# java -XX:+UseConcMarkSweepGC MyApp // 已移除
# 推荐使用 G1 或 ZGC
java -XX:+UseG1GC MyApp删除 Pack200 工具和 API
Java 14 移除了 Pack200 压缩工具和相关 API:
// 这些 API 在 Java 14 中已被移除
// Pack200.Packer packer = Pack200.newPacker();
// Pack200.Unpacker unpacker = Pack200.newUnpacker();预览特性
【了解】Records(预览)
Records 是 Java 14 引入的预览特性,用于创建不可变的数据载体类:
// 启用预览特性
// javac --enable-preview --release 14 RecordExample.java
// java --enable-preview RecordExample
// 定义一个简单的 Record
public record Person(String name, int age) {}
// 编译器自动生成:
// - 构造函数
// - getter 方法(name(), age())
// - equals() 和 hashCode()
// - toString()使用 Records:
public class RecordExample {
public static void main(String[] args) {
Person person = new Person("张三", 25);
System.out.println(person.name()); // 张三
System.out.println(person.age()); // 25
System.out.println(person.toString()); // Person[name=张三, age=25]
// Records 是不可变的
Person another = new Person("张三", 25);
System.out.println(person.equals(another)); // true
}
}Records 还支持自定义方法和验证:
public record BankAccount(String accountNumber, double balance) {
// 紧凑构造函数 - 用于验证
public BankAccount {
if (balance < 0) {
throw new IllegalArgumentException("余额不能为负数");
}
if (accountNumber == null || accountNumber.isBlank()) {
throw new IllegalArgumentException("账号不能为空");
}
}
// 自定义方法
public boolean isVIP() {
return balance > 100000;
}
// 静态工厂方法
public static BankAccount createSavingsAccount(String accountNumber) {
return new BankAccount(accountNumber, 0.0);
}
}【了解】instanceof 的模式匹配(预览)
Java 14 引入了 instanceof 的模式匹配作为预览特性:
// 传统写法
Object obj = "Hello World";
if (obj instanceof String) {
String str = (String) obj;
System.out.println("字符串长度: " + str.length());
}
// Java 14 模式匹配(预览)
if (obj instanceof String str) {
System.out.println("字符串长度: " + str.length());
}模式匹配的变量作用域:
public void processObject(Object obj) {
if (obj instanceof String str && str.length() > 5) {
System.out.println("长字符串: " + str);
// str 在这里可用
}
// str 在这里不可用
if (!(obj instanceof String str)) {
return;
}
// 由于前面的条件,这里 str 是可用的
System.out.println("字符串: " + str);
}【了解】文本块(第二次预览)
Java 14 继续完善文本块特性,添加了两个转义序列:
// \s - 表示空格
String text1 = """
Hello\sWorld
""";
// 结果: "Hello World\n"
// \ - 行末转义,避免换行
String text2 = """
This is a very long line that \
continues on the next line
""";
// 结果: "This is a very long line that continues on the next line\n"孵化器特性
【了解】打包工具(孵化器)
Java 14 引入了 jpackage 工具作为孵化器特性,可以将 Java 应用打包成平台特定的安装包:
# 创建可执行文件
jpackage --input target/ \
--name MyApp \
--main-jar myapp.jar \
--main-class com.example.Main
# 创建 Windows 安装包
jpackage --input target/ \
--name MyApp \
--main-jar myapp.jar \
--main-class com.example.Main \
--type msi
# 创建 macOS 安装包
jpackage --input target/ \
--name MyApp \
--main-jar myapp.jar \
--main-class com.example.Main \
--type dmg【了解】外部内存访问 API(孵化器)
Java 14 引入了外部内存访问 API,提供安全高效的堆外内存操作:
import jdk.incubator.foreign.*;
// 分配堆外内存
try (MemorySegment segment = MemorySegment.allocateNative(1024)) {
MemoryAddress address = segment.baseAddress();
// 写入数据
MemoryAccess.setIntAtOffset(segment, 0, 42);
MemoryAccess.setIntAtOffset(segment, 4, 24);
// 读取数据
int value1 = MemoryAccess.getIntAtOffset(segment, 0);
int value2 = MemoryAccess.getIntAtOffset(segment, 4);
System.out.println("值1: " + value1 + ", 值2: " + value2);
}
// 内存自动释放总结
Java 14 是一个重要的版本,Switch 表达式的正式化让条件判断更加优雅,改进的 NPE 信息让调试更加容易。Records 和 instanceof 模式匹配虽然还是预览特性,但已经显示出巨大的潜力。
GC 方面的改进,特别是 ZGC 的跨平台支持和 G1 的 NUMA 感知,为高性能应用提供了更多选择。JFR 事件流 API 则为实时监控开辟了新的可能性。Ea7H6DxcZeWlVJFFEnFyn3Lx21/mLUEMxr9P/hnm5xs=
虽然 Java 14 不是 LTS 版本,但它为后续版本奠定了重要基础,特别是 Records 和模式匹配等特性在后续版本中得到了进一步完善。