盘点JDK10的新特性

盘点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())); // 推断为 BufferedReader

1.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 应用建议

  1. 若项目追求“开发效率”,可优先使用 var 关键字和新增的集合 API,但需严格遵守 var 的使用限制,避免过度使用导致代码可读性下降;
  2. 若项目是大内存应用(堆内存 ≥ 16GB),升级 JDK10 可直接享受 G1 并行 Full GC 的优化,降低 STW 停顿风险;
  3. JDK10 不是 LTS 版本,官方支持周期较短(仅 6 个月),生产环境若需长期稳定支持,建议升级到 JDK11(LTS),但 JDK10 的核心特性(如 var、G1 优化)均被 JDK11 继承;
  4. 升级时注意兼容性:var 作为保留类型名,若项目中有用 var 作为类名/接口名,需修改名称;移除的 javah 工具需替换为 javac -h 命令。

六、总结

JDK10 虽然是过渡版本,但它的诸多优化的都是“承上启下”的关键——局部变量类型推断开启了 Java 语法简化的趋势,G1 垃圾回收器的优化为后续高并发、大内存应用奠定基础,API 的增强则贴合开发者的实际需求。

对于开发者而言,学习 JDK10 的特性,不仅能提升当下的开发效率,更能理解 Java 生态的演进方向(如语法简化、性能优化、安全性提升)。如果你的项目目前使用 JDK8 或 JDK9,升级到 JDK10(或直接到 JDK11),能快速享受这些优化带来的价值。

Read more

Python 驱动浏览器自动化:Playwright + AI 的 2026 最佳实践

Python 驱动浏览器自动化:Playwright + AI 的 2026 最佳实践

摘要:在 Web 自动化领域,Selenium 曾经的霸主地位已成历史,Playwright 凭其“快、稳、强”的现代特性成为了新标准。而在 2026 年,随着 LLM(大语言模型)和视觉多模态模型的爆发,自动化测试与 RPA(机器人流程自动化)迎来了范式革命。本文将深度解析 Playwright 的核心架构,并手把手教你构建一个具备“自愈能力”的 AI 驱动自动化 Agent。本文超 7000 字,包含大量实战代码与反爬对抗技巧。 第一章:Selenium 已死,Playwright 当立? 1.1 自动化的“不可能三角” 长期以来,Web 自动化工程师都在速度、稳定性和抗检测性之间做取舍: * Selenium:

By Ne0inhk
Windows上VSCode中配置MinGW、C++和手动自编译安装OpenCV(详细图文教程)

Windows上VSCode中配置MinGW、C++和手动自编译安装OpenCV(详细图文教程)

💪 专业从事且热爱图像处理,图像处理专栏更新如下👇: 📝《图像去噪》 📝《超分辨率重建》 📝《语义分割》 📝《风格迁移》 📝《目标检测》 📝《暗光增强》 📝《模型优化》 📝《模型实战部署》 📝《图像配准融合》 📝《数据集》 📝《高效助手》 📝《C++》 📝《Qt》 本教程是在电脑上已经安装了VSCode基础上讲解,如果没有安装VSCode的学者,自行先安装一下。 目录 * 一、MinGW安装 * 1.1 为什么先安装MinGW * 1.2 MinGW安装包下载 * 1.2.1 官网下载 * 1.2.2 github下载 * 1.3 添加环境变量 * 1.4 测试MinGW是否安装成功 * 二、OpenCV包 * 2.1 OpenCV包下载 * 2.2 添加环境变量 * 三、

By Ne0inhk
GraphQL在Python中的完整实现:从基础到企业级实战

GraphQL在Python中的完整实现:从基础到企业级实战

目录 摘要 1 引言:为什么GraphQL是API设计的未来 1.1 GraphQL的核心价值定位 1.2 GraphQL技术演进路线图 2 GraphQL核心技术原理深度解析 2.1 Schema定义语言与类型系统 2.1.1 Schema定义原则 2.1.2 类型系统架构 2.2 Resolver解析机制深度解析 2.2.1 Resolver执行模型 2.2.2 Resolver执行流程 2.3 Strawberry vs Graphene框架深度对比 2.3.1 架构设计哲学对比 2.3.2 框架选择决策树 3 实战部分:

By Ne0inhk

运行代码报错subprocess.CalledProcessError:Command ‘[‘which‘,‘c++‘]‘ returned non-zero exit status 1.

我现在是要在x86_64麒麟系统电脑上运行我的代码,结果出现下面的报错信息: subprocess.CalledProcessError: Command '['which', 'c++']' returned non-zero exit status 1 出现这个问题的原因是Python 或系统脚本调用 which c++ 时,系统没有找到 c++ 编译器。其根本原因可能是: * 系统中没有安装 g++ 或 build-essential; * 或者虽然安装了,但没有加入 PATH; * 或者安装到了非默认路径(比如 /home/xxx/mygcc)。  然后我就开始尝试安装这个g++,我的系统是 银河麒麟 V10(x86_64),电脑不能联网,所以就分为在线安装和离线安装两种形式。 1、在线安装

By Ne0inhk