1. 概述
2019年9月,JDK 13 正式发布,延续了Java每六个月一次的发布节奏。本文将深入解析该版本引入的核心新特性与改进点,帮助开发者快速掌握关键变化。
2. 预览版语言特性
Java 13 引入了两个处于“预览”状态的语言特性。这意味着它们功能完整、可用于评估,但尚未正式生产就绪。未来版本可能根据社区反馈决定是否保留或转正。
⚠️ 要使用这些预览功能,必须在编译和运行时显式添加 --enable-preview
命令行参数。
2.1. Switch 表达式(JEP 354)
Switch 表达式最早出现在 JDK 12 中,而 Java 13 在其基础上引入了全新的 yield
关键字,用于从 switch
块中返回值。
✅ 使用 yield
后,switch
不再局限于 break
和 return
,逻辑更清晰,也更容易实现类似策略模式的结构:
@Test
@SuppressWarnings("preview")
public void whenSwitchingOnOperationSquareMe_thenWillReturnSquare() {
var me = 4;
var operation = "squareMe";
var result = switch (operation) {
case "doubleMe" -> {
yield me * 2;
}
case "squareMe" -> {
yield me * me;
}
default -> me;
};
assertEquals(16, result);
}
📌 踩坑提示:yield
只能在 case
的 {}
块中使用,不能用于箭头语法(->
)直接表达的单行语句。
2.2. 文本块(Text Blocks,JEP 355)
这是 Java 13 最受欢迎的预览特性之一,专为处理多行字符串设计,比如嵌入 JSON、XML、HTML 等内容。
❌ 以往写法繁琐且易错:
String JSON_STRING
= "{\r\n" + "\"name\" : \"Baeldung\",\r\n" + "\"website\" : \"https://www.%s.com/\"\r\n" + "}";
✅ 使用文本块后,代码简洁直观,无需转义引号或手动换行:
String TEXT_BLOCK_JSON = """
{
"name" : "Baeldung",
"website" : "https://www.%s.com/"
}
""";
所有 String
的方法依然可用:
@Test
public void whenTextBlocks_thenStringOperationsWorkSame() {
assertThat(TEXT_BLOCK_JSON.contains("Baeldung")).isTrue();
assertThat(TEXT_BLOCK_JSON.indexOf("www")).isGreaterThan(0);
assertThat(TEXT_BLOCK_JSON.length()).isGreaterThan(0);
}
此外,String
类新增了三个专为文本块设计的方法:
stripIndent()
:自动去除每行前导空格(编译器级智能去缩进)translateEscapes()
:将转义序列如\\t
解析为\t
formatted(...)
:等价于String.format
,但专为文本块设计
示例:使用 formatted
动态填充域名
assertThat(TEXT_BLOCK_JSON.formatted("baeldung").contains("www.baeldung.com")).isTrue();
assertThat(String.format(JSON_STRING,"baeldung").contains("www.baeldung.com")).isTrue();
⚠️ 注意:由于文本块仍为预览特性,上述新方法在 JDK 13 中被标记为 **@Deprecated(forRemoval = true)**,意为未来可能移除。
3. 动态 CDS 归档(JEP 350)
CDS(Class Data Sharing)是 HotSpot VM 的经典优化手段,通过共享类元数据来降低 JVM 启动时间和内存占用。JDK 10 引入了 AppCDS,允许将应用类加入共享归档;JDK 12 默认启用系统级 CDS 归档。
但传统流程太麻烦:必须先试运行应用生成类列表,再手动导出归档文件,步骤繁琐且容易出错。
Java 13 的 动态 CDS 归档解决了这个问题——应用退出时自动将已加载的类写入归档文件,省去了预运行步骤。
使用方式简单粗暴:
- 第一次运行时启用归档生成:
java -XX:ArchiveClassesAtExit=myapp.jsa -cp myapp.jar com.example.Main
- 后续运行直接加载归档:
java -XX:SharedArchiveFile=myapp.jsa -cp myapp.jar com.example.Main
✅ 效果:显著提升微服务冷启动速度,尤其适合容器化部署场景。
4. ZGC:释放未使用内存(JEP 351)
ZGC(Z Garbage Collector)自 Java 11 起作为低延迟 GC 方案登场,承诺 GC 停顿时间不超过 10ms。但早期版本有个硬伤:无法将空闲堆内存归还给操作系统,导致长期运行服务内存“只增不减”。
Java 13 为 ZGC 补上了这块拼图:
✅ ZGC 现在默认会将未提交的堆内存释放回操作系统,直到达到 -Xms
设置的最小堆大小。
如果不想启用此功能,有两种方式回退到 Java 11 行为:
- 使用
-XX:-ZUncommit
- 设置
-Xms
与-Xmx
相等(禁用堆动态伸缩)
此外,ZGC 最大堆支持从 4TB 提升至 16TB,进一步拓宽了其在超大内存场景下的适用性。
5. 重构遗留 Socket API(JEP 353)
java.net.Socket
和 ServerSocket
是 Java 最古老的 API 之一,底层由陈旧的 Java/C 混合代码实现,维护困难,且与现代 NIO 架构脱节。
Java 13 将其底层实现从 PlainSocketImpl
替换为基于 java.nio
的 NioSocketImpl
,带来以下好处:
- ✅ 更简洁的代码结构
- ✅ 更好的可维护性
- ✅ 为未来支持虚拟线程(Virtual Threads)铺路
⚠️ 兼容性考虑:可通过 JVM 参数切换回旧实现:
-Djdk.net.usePlainSocketImpl=true
默认值为 false
,即使用新的 NioSocketImpl
。
6. 其他重要变更
除上述 JEP 外,Java 13 还包含多项实用改进:
新增 API
java.nio
:新增FileSystems.newFileSystem(Path, Map<String, ?>)
,简化文件系统挂载java.time
:支持日本新年号「令和」(Reiwa)javax.crypto
:支持 Windows 的 CNG(Cryptography Next Generation)加密框架javax.security
:新增jdk.sasl.disabledMechanisms
属性,用于禁用特定 SASL 认证机制javax.xml.crypto
:新增 Canonical XML 1.1 的 URI 常量javax.xml.parsers
:支持带命名空间的 DOM/SAX 工厂实例化
基础设施升级
- Unicode 升级至 12.1 版本
- Kerberos 支持主体名称规范化和跨域跳转(cross-realm referrals)
已标记待移除的 API
以下 API 已被标记为废弃,未来版本可能移除:
- 三个
String
方法(与文本块冲突) javax.security.cert
包rmic
工具(RMI 编译器)- Javadoc 工具中的老旧功能
- 所有 JDK 1.4 之前的
SocketImpl
自定义实现
7. 总结
Java 13 虽然没有引入革命性语法变更,但在性能优化、API 现代化和开发者体验上做了扎实改进。特别是:
- ✅ 文本块极大简化了多行字符串处理
- ✅ 动态 CDS 降低了应用启动开销
- ✅ ZGC 内存回收让低延迟 GC 更加实用
- ✅ Socket 重构为未来虚拟线程打下基础
尽管部分特性仍处于预览阶段,但已足够在非生产环境尝试。建议开发者结合 --enable-preview
在新项目中体验这些特性,为未来升级做好准备。
所有示例代码已托管至 GitHub:https://github.com/baeldung/tutorials/tree/master/core-java-modules/core-java-13