盘点JDK10的新特性
JDK10 是 Java 生态在 2018 年 3 月发布的重要版本,作为 Java 采用半年度发布节奏后的首个版本,它虽非 LTS(长期支持)版本,却承载了诸多关键优化——既有简化开发的语法特性,也有提升 JVM 性能的底层改进,更有完善 API 的实用更新。本文将针对开发者日常开发场景,盘点 JDK10 最值得关注的核心新特性,搭配代码示例和实际应用场景,帮大家快速掌握其价值与用法。

先明确一个基础认知:JDK10 共包含 12 个 JEP(Java 增强提议)和 109 项新特性,本文聚焦“开发者高频接触”的特性,避免罗列冷门内容,兼顾专业性与实用性。
一、核心语法特性:局部变量类型推断(var 关键字)
这是 JDK10 最受开发者关注的新特性,也是唯一直接影响日常编码风格的语法优化——引入 var 关键字,允许开发者声明局部变量时省略显式类型,由编译器根据初始化表达式自动推断变量类型,减少冗余代码,提升可读性。
1.1 基本用法(代码示例)
在 JDK10 之前,我们声明局部变量必须显式指定类型,即便右侧已经明确了具体实现:
// JDK10 之前的写法(冗余) ArrayList<String> list = new ArrayList<String>(); URL url = new URL("http://www.oracle.com/"); URLConnection conn = url.openConnection(); BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); JDK10 中使用 var 后,代码可简化为:
// JDK10 简化写法(编译器自动推断类型) var list = new ArrayList<String>(); // 推断为 ArrayList<String> var url = new URL("http://www.oracle.com/"); // 推断为 URL var conn = url.openConnection(); // 推断为 URLConnection var reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); // 推断为 BufferedReader1.2 适用场景
- 方法体内的局部变量(最常用场景);
- 增强 for 循环的循环变量;
- 传统 for 循环的索引变量;
- try-with-resources 语句中的资源变量;
- JDK11 及后续版本中,可用于隐式类型 lambda 表达式的参数(JDK10 暂不支持)。
// 增强 for 循环示例 List<String> myList = Arrays.asList("Java", "JDK10", "Var"); for (var element : myList) { // 推断为 String System.out.println(element); } // 传统 for 循环示例 for (var i = 0; i < 10; i++) { // 推断为 int System.out.println(i); } // try-with-resources 示例 try (var input = new FileInputStream("test.txt")) { // 推断为 FileInputStream // 读取文件操作 } catch (IOException e) { e.printStackTrace(); } 1.3 关键限制(必看!避免踩坑)
很多开发者会误以为 var 是“动态类型”,实则不然——它是“静态类型推断”,编译期就确定变量类型,运行时类型不变,且有严格的使用限制:
- 不能用于成员变量(类级别的变量);
- 不能用于方法参数和返回值;
- 声明时必须初始化(编译器需要通过初始化表达式推断类型);
- 不能初始化为 null(无法推断具体类型);
- 不能用于数组初始化(除非有明确的初始化值);
var是“保留类型名”,不是关键字——意味着 existing 代码中用 var 作为变量名、方法名、包名不受影响,但不能用 var 作为类名或接口名。
// 错误用法示例(JDK10 中编译失败) var name; // 错误:未初始化,无法推断类型 var list = null; // 错误:初始化为 null,无法推断具体类型 class var { } // 错误:不能用 var 作为类名 // 正确用法示例 var arr = new int[]{1, 2, 3}; // 正确:有明确初始化值,推断为 int[] 二、JVM 底层优化:垃圾回收器升级
JDK10 对垃圾回收机制进行了两项关键优化,均围绕“提升性能、降低延迟”展开,尤其适合大内存应用场景,无需修改代码即可享受优化效果。
2.1 G1 垃圾回收器的并行 Full GC(JEP 307)
G1 垃圾回收器自 JDK9 起成为默认 GC,但 JDK10 之前,G1 的 Full GC 是单线程执行的——当 G1 无法跟上堆内存碎片产生的速度时,会退化为 Serial GC 执行 Full GC,在大内存堆(如 16GB 以上)中会导致几秒甚至更久的 STW(Stop-The-World)停顿,成为性能瓶颈。
JDK10 的优化的核心:将 G1 的 Full GC 过程并行化,利用多核 CPU 资源,让多个线程同时处理标记、清理和压缩阶段,大幅缩短 STW 时间。
优化细节与效果:
- 技术实现:基于 G1 的 Region 分区机制,多个线程并行处理不同 Region 的垃圾回收;通过 Remembered Set(RSet)快速定位跨 Region 的引用,减少扫描范围;引入
G1FullGCCompactionPoint组件优化对象移动和内存压缩。 - 性能提升:在大内存应用中,Full GC 停顿时间可缩短 50% 以上,无需额外配置 JVM 参数,默认启用该优化。
2.2 统一垃圾回收器接口(JEP 304)
这是一项“底层架构优化”,目的是重构 GC 代码,建立统一的接口框架,将 GC 实现与 JVM 核心代码解耦。
对普通开发者而言,直接感知不强,但对 JVM 开发者和后续 GC 算法的集成意义重大:
- 简化新 GC 算法的集成和维护(如后续 JDK 引入的 Shenandoah、ZGC 垃圾回收器,均受益于该接口);
- 提供标准化的 GC 配置和监控 API,方便开发者切换和调优不同 GC 算法。
三、API 增强:实用工具类升级
JDK10 对多个核心工具类新增了实用方法,无需自己封装,直接调用即可提升开发效率,重点关注以下 3 类。
3.1 Optional 类新增 orElseThrow() 方法(JDK-8140281)
Optional 类是 Java 8 引入的用于处理空指针的工具类,JDK10 为其新增了 orElseThrow()方法,用于“当 Optional 为空时抛出异常,不为空时返回实际值”。
该方法是 get() 方法的首选替代方案——get() 方法在 Optional 为空时会抛出 NoSuchElementException,而 orElseThrow() 语法更清晰,语义更明确。
// JDK10 之前的写法 Optional<String> optional = Optional.ofNullable(null); String value = optional.get(); // 空值时抛出 NoSuchElementException // JDK10 新写法(推荐) Optional<String> optional = Optional.ofNullable(null); String value = optional.orElseThrow(); // 空值时抛出 NoSuchElementException,语义更清晰 // 也可自定义异常 String value2 = optional.orElseThrow(() -> new RuntimeException("值不存在")); 3.2 集合工具类新增不可变集合创建 API(JDK-8177290)
JDK10 之前,创建不可变集合需要借助Collections.unmodifiableList() 等方法,语法繁琐且存在“修改原始集合会影响不可变集合”的隐患。
JDK10 新增了 3 个静态方法,用于快速创建不可变集合:
List.copyOf(Collection):从现有集合创建不可变 List;Set.copyOf(Collection):从现有集合创建不可变 Set;Map.copyOf(Map):从现有 Map 创建不可变 Map。
同时,Stream 流的 Collectors 类也新增了 toUnmodifiableList()、toUnmodifiableSet()、toUnmodifiableMap() 方法,支持将流结果直接收集为不可变集合。
// 1. 从现有集合创建不可变集合 List<String> originalList = new ArrayList<>(Arrays.asList("a", "b", "c")); List<String> unmodifiableList = List.copyOf(originalList); // unmodifiableList.add("d"); // 抛出 UnsupportedOperationException // 2. Stream 流收集为不可变集合 List<String> streamList = Stream.of("x", "y", "z") .collect(Collectors.toUnmodifiableList()); // streamList.remove(0); // 抛出 UnsupportedOperationException 核心优势:创建的不可变集合是“真正的不可变”,不允许添加、删除、修改元素,且不受原始集合的影响(原始集合修改不会同步到不可变集合)。
3.3 其他实用 API 优化
- Unicode 语言标签扩展(JEP 314):增强
java.util.Locale类及相关 API,支持 BCP 47 语言标签的额外 Unicode 扩展,包括货币类型(cu)、每周第一天(fw)、区域覆盖(rg)、时区(tz)等,方便开发多语言、多区域适配的应用。 - JMX 代理密码哈希(JEP 未单独编号):JMX 远程代理的
jmxremote.password文件中,明文密码会被自动替换为 SHA-3-512 哈希值,提升安全性,无需手动处理密码加密。 - 禁用 JRE 最后使用追踪(JDK-8192039):新增系统属性
jdk.disableLastUsageTracking,通过-Djdk.disableLastUsageTracking=true即可禁用 JRE 最后使用追踪,避免不必要的资源占用。
四、其他重要特性与优化
4.1 应用类数据共享(CDS)增强(JEP 310)
CDS(Class-Data Sharing)是 JDK5 引入的特性,用于改善 JVM 启动速度、减少多虚拟机运行时的资源占用——通过将类的元数据缓存到共享归档文件中,多个 JVM 进程可共享该归档文件,避免重复加载类。
JDK10 对 CDS 进行了扩展:之前 CDS 仅支持 bootstrap 类加载器加载的类,JDK10 允许内部系统类加载器、内部平台类加载器和自定义类加载器加载的类加入共享归档,进一步提升启动速度和内存利用率,尤其适合微服务集群、多实例部署场景。
4.2 线程局部握手(JEP 312)
引入一种“无需执行全局 VM 安全点”即可在单个线程上执行回调的方法,实现“精准停止单个线程”,而不是传统的“停止所有线程或不停止任何线程”。
该特性主要用于 JVM 内部优化(如线程中断、线程本地资源清理),对普通开发者而言,虽然不直接使用,但能提升 JVM 对线程的管理效率,间接优化多线程应用的性能。
4.3 基于时间的版本控制(JEP 322)
修订 JDK 的版本字符串方案,适配半年度发布节奏,新的版本格式为:$FEATURE.$INTERIM.$UPDATE.$PATCH
FEATURE:主版本号,每 6 个月递增(如 JDK10 为 10,JDK11 为 11);INTERIM:临时更新,永远为 0(预留用于未来非计划更新);UPDATE:安全更新和 bug 修复,每 1 个月递增;PATCH:紧急修复,按需发布。
该方案解决了 JDK9 及之前版本号混乱的问题,让开发者能更清晰地判断版本迭代节奏和更新内容。
4.4 其他优化
- 实验性 Graal JIT 编译器(JEP 317):在 Linux/x64 平台上,支持启用基于 Java 的 Graal 编译器作为实验性 JIT 编译器,相比传统 JIT 编译器,Graal 在某些场景下能提升代码执行效率(需通过 JVM 参数
-XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler启用)。 - 替代内存设备堆分配(JEP 316):允许 HotSpot 虚拟机在用户指定的替代内存设备(如 NV-DIMM)上分配 Java 对象堆,满足特殊场景下的内存需求。
- 根证书支持(JEP 319):JDK 中提供默认的 CA 根证书集合,让 OpenJDK 构建版本的 TLS 等安全功能默认有效,无需额外配置证书。
- 移除 Native-Header 自动生成工具(JEP 313):JDK9 开始逐步清理冗余工具,JDK10 正式移除
javah工具,开发者可通过javac -h命令生成 JNI 头文件,简化开发流程。
五、JDK10 特性总结与应用建议
5.1 核心特性总结
JDK10 的特性可分为三大类,贴合不同开发者的需求:
- 面向普通开发者:局部变量类型推断(var)、集合不可变创建 API、Optional.orElseThrow(),直接简化编码,提升开发效率;
- 面向运维/调优工程师:G1 并行 Full GC、CDS 增强,无需修改代码即可提升应用性能和启动速度;
- 面向 JVM/框架开发者:统一 GC 接口、线程局部握手,为底层开发和框架优化提供支持。
5.2 应用建议
- 若项目追求“开发效率”,可优先使用 var 关键字和新增的集合 API,但需严格遵守 var 的使用限制,避免过度使用导致代码可读性下降;
- 若项目是大内存应用(堆内存 ≥ 16GB),升级 JDK10 可直接享受 G1 并行 Full GC 的优化,降低 STW 停顿风险;
- JDK10 不是 LTS 版本,官方支持周期较短(仅 6 个月),生产环境若需长期稳定支持,建议升级到 JDK11(LTS),但 JDK10 的核心特性(如 var、G1 优化)均被 JDK11 继承;
- 升级时注意兼容性:var 作为保留类型名,若项目中有用 var 作为类名/接口名,需修改名称;移除的 javah 工具需替换为 javac -h 命令。
六、总结
JDK10 虽然是过渡版本,但它的诸多优化的都是“承上启下”的关键——局部变量类型推断开启了 Java 语法简化的趋势,G1 垃圾回收器的优化为后续高并发、大内存应用奠定基础,API 的增强则贴合开发者的实际需求。
对于开发者而言,学习 JDK10 的特性,不仅能提升当下的开发效率,更能理解 Java 生态的演进方向(如语法简化、性能优化、安全性提升)。如果你的项目目前使用 JDK8 或 JDK9,升级到 JDK10(或直接到 JDK11),能快速享受这些优化带来的价值。