Java 10 新特性概览
Java 10 发布于 2018 年 3 月 20 日,这是一个非 LTS(长期支持)版本,Oracle 仅提供六个月的支持。
下图是从 JDK 8 到 JDK 25 每个版本的更新带来的新特性数量和更新时间:

这篇文章会挑选其中较为重要的一些新特性进行详细介绍:
- JEP 286: Local-Variable Type Inference(局部变量类型推断)
- JEP 304: Garbage-Collector Interface(垃圾回收器接口)
- JEP 307: Parallel Full GC for G1(G1 并行 Full GC)
- JEP 310: Application Class-Data Sharing(应用程序类数据共享)
- JEP 317: Experimental Java-Based JIT Compiler(实验性的基于 Java 的 JIT 编译器)
JEP 286: Local-Variable Type Inference
📝 通俗解释
- var (类型推断):自动识别。
- 以前:
ArrayList<String> list = new ArrayList<String>();(啰嗦)。- 现在:
var list = new ArrayList<String>();(清爽)。- 编译器会根据后面的
new ArrayList...自动推断出list是什么类型。你懒得写,编译器帮你补。
由于太多 Java 开发者希望 Java 中引入局部变量类型推断,于是 Java 10 的时候它来了,也算是众望所归了!
Java 10 提供了 var 关键字声明局部变量。
var id = 0;
var codefx = new URL("https://mp.weixin.qq.com/");
var list = new ArrayList<>();
var list = List.of(1, 2, 3);
var map = new HashMap<String, String>();
var p = Paths.of("src/test/java/Java9FeaturesTest.java");
var numbers = List.of("a", "b", "c");
for (var n : numbers)
System.out.print(n+ " ");var 关键字只能用于带有构造器的局部变量和 for 循环中。
var count = null; //❌编译不通过,不能声明为 null
var r = () -> Math.random();//❌编译不通过,不能声明为 Lambda表达式
var array = {1, 2, 3};//❌编译不通过,不能声明数组var 并不会改变 Java 是一门静态类型语言的事实,编译器负责推断出类型。
另外,Scala 和 Kotlin 中已经有了 val 关键字 ( final var 组合关键字)。
JEP 304: Garbage-Collector Interface
📝 通俗解释
- GC 接口:代码整洁。
- 这主要是给 JVM 开发者看的。以前各种 GC 的代码(G1, CMS, Parallel)混在一起,像一团乱麻。
- 现在定义了一套标准接口,想加一个新的 GC,只要实现这个接口就行,不用去改别人的代码。这也是为了后面 ZGC、Shenandoah 的加入铺路。
在早期的 JDK 结构中,组成垃圾收集器 (GC) 实现的组件分散在代码库的各个部分。 Java 10 通过引入一套纯净的垃圾收集器接口来将不同垃圾收集器的源代码分隔开。
JEP 307: Parallel Full GC for G1
📝 通俗解释
- G1 并行 Full GC:人多力量大。
- 以前 G1 如果不得不进行一次彻底大扫除(Full GC),它是单线程干活,慢死人,系统会卡很久。
- 现在允许并行多线程一起大扫除,速度快多了,系统卡顿时间变短。
从 Java 9 开始 G1 就成了默认的垃圾回收器,G1 是以一种低延时的垃圾回收器来设计的,旨在避免进行 Full GC,但是 Java 9 的 G1 的 Full GC 依然是使用单线程去完成标记清除算法,这可能会导致垃圾回收器在无法回收内存的时候触发 Full GC。
为了最大限度地减少 Full GC 造成的应用停顿的影响,从 Java10 开始,G1 的 FullGC 改为并行的标记清除算法,同时会使用与年轻代回收和混合回收相同的并行工作线程数量,从而减少了 Full GC 的发生,以带来更好的性能提升、更大的吞吐量。
JEP 310: 应用程序类数据共享(扩展 CDS 功能)
在 Java 5 中就已经引入了类数据共享机制 (Class Data Sharing,简称 CDS),允许将一组类预处理为共享归档文件,以便在运行时能够进行内存映射以减少 Java 程序的启动时间,当多个 Java 虚拟机(JVM)共享相同的归档文件时,还可以减少动态内存的占用量,同时减少多个虚拟机在同一个物理或虚拟的机器上运行时的资源占用。CDS 在当时还是 Oracle JDK 的商业特性。
Java 10 在现有的 CDS 功能基础上再次拓展,以允许应用类放置在共享存档中。CDS 特性在原来的 bootstrap 类基础之上,扩展加入了应用类的 CDS 为 (Application Class-Data Sharing,AppCDS) 支持,大大加大了 CDS 的适用范围。其原理为:在启动时记录加载类的过程,写入到文本文件中,再次启动时直接读取此启动文本并加载。设想如果应用环境没有大的变化,启动速度就会得到提升。
📝 通俗解释
- AppCDS:启动加速器。
- JVM 启动时要加载很多类,很慢。
- CDS 就是把加载好的类数据存成一个文件(存档)。下次启动,直接读存档,不用再解析 class 文件了。
- 以前只支持 JDK 自带的类(Bootstrap),现在连你写的类(Application)也能存档了。对于微服务这种频繁启停的场景很有用。
JEP 317: 实验性的基于 Java 的 JIT 编译器
Graal 是一个基于 Java 语言编写的 JIT 编译器,是 JDK 9 中引入的实验性 Ahead-of-Time (AOT) 编译器的基础。
Oracle 的 HotSpot VM 便附带两个用 C++ 实现的 JIT compiler:C1 及 C2。在 Java 10 (Linux/x64, macOS/x64) 中,默认情况下 HotSpot 仍使用 C2,但通过向 java 命令添加 -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler 参数便可将 C2 替换成 Graal。
📝 通俗解释
- Graal 编译器:用 Java 写 Java 编译器。
- 以前 JVM 的即时编译器(C2)是用 C++ 写的,很难改,也很难维护。
- Graal 是用 Java 写的编译器,不仅更容易维护,而且优化能力非常强。它也是后来 GraalVM 的核心技术。
API 增强
📝 通俗解释
- API 增强:查漏补缺。
- 主要是 List/Set/Map 加了
copyOf,Optional 加了orElseThrow。
并不是所有的 API 改动都会通过 JEP(Java Enhancement Proposal)来发布。
在 JDK 的开发流程中:JEP 通常用于重大的改变,例如引入新的语言特性(如 var)、新的 JVM 机制(如 ZGC)或者大规模的库重构。像 List.copyOf() 这种在现有类中增加几个静态方法的操作,通常被视为常规的库维护。它们由 JDK 开发者直接通过 JBS (JDK Bug System) 的工单(Ticket)进行提交和评审,然后随版本直接发布。
集合增强
List,Set,Map 提供了静态方法copyOf()返回入参集合的一个不可变拷贝。
static <E> List<E> copyOf(Collection<? extends E> coll) {
return ImmutableCollections.listCopy(coll);
}使用 copyOf() 创建的集合为不可变集合,不能进行添加、删除、替换、 排序等操作,不然会报 java.lang.UnsupportedOperationException 异常。 IDEA 也会有相应的提示。

并且,java.util.stream.Collectors 中新增了静态方法,用于将流中的元素收集为不可变的集合。
var list = new ArrayList<>();
list.stream().collect(Collectors.toUnmodifiableList());
list.stream().collect(Collectors.toUnmodifiableSet());📝 通俗解释
- copyOf / toUnmodifiable:不可变集合。
- 想要一个只读的 List?直接
List.copyOf(oldList)。- 安全、高效,不用担心被别人偷偷改了。
Optional 增强
Optional 新增了一个无参的 orElseThrow() 方法,作为带参数的 orElseThrow(Supplier<? extends X> exceptionSupplier) 的简化版本,在没有值时默认抛出一个 NoSuchElementException 异常。
Optional<String> optional = Optional.empty();
String result = optional.orElseThrow();📝 通俗解释
- orElseThrow():更直接的报错。
- 以前 Optional 为空时想抛异常,得写
orElseThrow(() -> new NoSuchElementException())。- 现在直接
orElseThrow(),默认就抛NoSuchElementException,少写几个字。
其他
- 线程-局部管控:Java 10 中线程管控引入 JVM 安全点的概念,将允许在不运行全局 JVM 安全点的情况下实现线程回调,由线程本身或者 JVM 线程来执行,同时保持线程处于阻塞状态,这种方式使得停止单个线程变成可能,而不是只能启用或停止所有线程
- 备用存储装置上的堆分配:Java 10 中将使得 JVM 能够使用适用于不同类型的存储机制的堆,在可选内存设备上进行堆内存分配
- ……
📝 通俗解释
- 线程管控:不用为了停一个线程把所有线程都停下来(Stop The World),减少卡顿。
- 堆分配:能把堆内存分配到一种叫 NVDIMM 的新型内存条上(断电数据还在),提升大数据处理性能。
参考
Java 10 Features and Enhancements : https://howtodoinjava.com/java10/java10-features/
Guide to Java10 : https://www.baeldung.com/java-10-overview
4 Class Data Sharing : https://docs.oracle.com/javase/10/vm/class-data-sharing.htm#JSJVM-GUID-7EAA3411-8CF0-4D19-BD05-DF5E1780AA91
