1. 引言
Java SE 10 的官方实现 JDK 10 于 2018 年 3 月 20 日正式发布。这次更新虽然不像 Java 8 那样带来革命性变化,但依然引入了不少实用的新特性与底层优化,尤其在开发体验、容器支持和性能调优方面有明显提升。
本文将系统梳理 Java 10 中的关键更新,帮助你快速掌握核心变化,避免踩坑,也为后续升级提供参考。
2. 局部变量类型推断(var)
这是 Java 10 最受关注的新特性,允许使用 var
关键字声明局部变量,由编译器自动推断类型。
✅ 适用场景:
- 变量初始化时右侧已明确类型
- 提升代码可读性(尤其在泛型复杂时)
❌ 不适用场景:
- 初始化值为
null
- Lambda 表达式或方法引用(编译器无法推断)
示例代码
@Test
public void givenValidStatements_whenUsingVar_thenSuccess() {
var name = "Java 10"; // 推断为 String
var list = List.of(1, 2, 3); // 推断为 List<Integer>
var stream = list.stream() // 推断为 Stream<Integer>
.filter(i -> i > 1);
assertEquals("Java 10", name);
assertTrue(stream.count() == 2);
}
⚠️ 注意:var
仅用于局部变量,不能用于字段、方法参数或返回类型。
更深入的用法和限制,建议查看专题文章:Java 10 局部变量类型推断
3. 不可变集合增强
Java 10 对不可变集合的支持更加友好,新增了两个便捷方法,避免手动包装或使用 Collections.unmodifiableXXX()
。
3.1 List.copyOf()
, Set.copyOf()
, Map.copyOf()
直接从已有集合创建不可变副本,简单粗暴。
@Test(expected = UnsupportedOperationException.class)
public void whenModifyCopyOfList_thenThrowsException() {
List<Integer> original = Arrays.asList(1, 2, 3);
List<Integer> copyList = List.copyOf(original);
copyList.add(4); // ❌ 抛出 UnsupportedOperationException
}
✅ 特点:
- 若原集合已是不可变的,
copyOf()
可能直接返回原引用(性能优化) - 空集合传入会返回标准的不可变空集合
3.2 Collectors.toUnmodifiableList/Set/Map
在 Stream 流水线中直接收集为不可变集合,告别中间可变状态。
@Test(expected = UnsupportedOperationException.class)
public void whenModifyToUnmodifiableList_thenThrowsException() {
List<Integer> evenList = someIntList.stream()
.filter(i -> i % 2 == 0)
.collect(Collectors.toUnmodifiableList());
evenList.add(4); // ❌ 同样抛异常
}
✅ 建议:在构建配置、缓存数据等场景优先使用,防止意外修改。
4. Optional.orElseThrow()
Optional
家族新增无参 orElseThrow()
方法,语义更清晰,**推荐替代 get()
**。
@Test
public void whenListContainsInteger_OrElseThrowReturnsInteger() {
Integer firstEven = someIntList.stream()
.filter(i -> i % 2 == 0)
.findFirst()
.orElseThrow(); // 没有值时自动抛出 NoSuchElementException
assertEquals(Integer.valueOf(2), firstEven);
}
✅ 优势:
- 相比
get()
,orElseThrow()
明确表达了“期望有值,否则失败”的意图 - 异常类型固定为
NoSuchElementException
,便于统一处理
虽然行为与
get()
一致,但从代码可读性和最佳实践角度,应优先使用orElseThrow()
。
5. 性能改进
Java 10 在底层做了多项性能优化,包括:
- G1 垃圾回收器并行 Full GC 支持
- 减少 GC 暂停时间
- 字符串压缩优化
这些改进对应用透明,无需代码改动即可受益。
深入细节可参考:Java 10 性能提升详解
6. 容器环境感知能力
✅ 重大改进:JVM 现在能识别运行在 Docker 容器中,并自动读取容器限制(如 CPU 数、内存),而非宿主机资源。
适用平台
- 仅支持 Linux(因依赖 cgroups)
默认行为
- ✅ 启用容器支持:
-XX:+UseContainerSupport
(默认开启) - ❌ 可手动关闭:
-XX:-UseContainerSupport
新增关键参数
参数 | 说明 |
---|---|
-XX:ActiveProcessorCount=count |
指定 JVM 使用的 CPU 核心数 |
-XX:InitialRAMPercentage=xx |
初始堆内存占容器总内存百分比(默认 1.56%) |
-XX:MaxRAMPercentage=xx |
最大堆内存占比(默认 25%) |
-XX:MinRAMPercentage=xx |
最小堆内存占比 |
📌 踩坑提醒:
在 Kubernetes 或 Docker 中部署时,若未设置内存限制,JVM 可能误判可用内存,导致 OOM。建议始终通过 -XX:MaxRAMPercentage
显式控制堆大小。
7. 根证书支持(Root Certificates)
OpenJDK 长期以来因缺少默认信任的根证书,导致 HTTPS、TLS 等安全协议无法开箱即用。
Java 10 起,Oracle 将其 Java SE Root CA 计划中的根证书开源,集成进 OpenJDK 的 cacerts
密钥库。
✅ 影响:
- OpenJDK 构建版本 now supports TLS out of the box
- 缩小了 OpenJDK 与 Oracle JDK 的差距
- 开发者不再需要手动导入根证书
8. 已废弃和移除的内容
8.1 命令行工具移除
以下工具已被移除,建议使用替代方案:
已移除工具 | 替代方案 | 说明 |
---|---|---|
javah |
javac -h |
生成 JNI 头文件 |
policytool |
文本编辑器 | 管理 java.policy 文件 |
java -Xprof |
jmap , jstat , Async-Profiler |
性能分析 |
8.2 API 标记为待移除
以下 API 已被标记 forRemoval = true
,未来版本将删除:
java.security.acl
包 ❌(推荐使用java.security.Policy
)java.security.Certificate
java.security.Identity
,IdentityScope
,Signer
⚠️ 建议:新项目避免使用,老项目尽早迁移。
9. 基于时间的版本发布模型
从 Java 10 开始,Oracle 正式采用时间驱动发布模式,彻底改变 Java 的演进节奏。
核心规则
✅ 每六个月发布一个新版本
- 例如:JDK 10(2018.03)、JDK 11(2018.09)
✅ 功能版本支持周期为六个月
- 仅维护到下一个版本发布为止
✅ 长期支持版本(LTS)每三年发布一次,支持三年
- JDK 11 是第一个 LTS 版本(后续为 JDK 17、JDK 21...)
✅
java -version
输出包含 GA 日期,便于判断版本新旧
$ java -version
openjdk version "10" 2018-03-20
OpenJDK Runtime Environment 18.3 (build 10+46)
OpenJDK 64-Bit Server VM 18.3 (build 10+46, mixed mode)
📌 对开发者的启示:
- 普通功能版本适合尝鲜,生产环境应优先选择 LTS 版本
- 升级周期变短,需建立持续跟进机制
10. 总结
Java 10 虽然是一个短期功能版本,但引入了多项影响深远的改进:
var
提升编码效率- 不可变集合 API 更加现代化
- 容器支持补齐云原生短板
- 发布模型转向敏捷迭代
尽管 JDK 11 才是首个 LTS 版本,但 Java 10 标志着 Java 进入高速迭代时代。建议开发者理解其变化,为后续升级做好准备。
所有示例代码已托管至 GitHub:https://github.com/eugenp/tutorials/tree/master/core-java-modules/core-java-10