Skip to content
<

Java 10 于 2018年3月发布,这是 Java 采用新发布周期后的第一个版本。虽然特性不多,但引入了备受关注的 var 关键字,让 Java 代码可以更加简洁。

正式特性

【实用】局部变量类型推断(var)

用过弱类型编程语言的朋友应该⁢知道,不用自己声明⁡变量的类型有多爽。

但是对于 Java 这种强类⁢型语言,我们经常要⁡写下面这种代码,一⁡个变量类型写老长(特别是在泛型场景下):

java
Map<String, List<Integer>> complexMap = new HashMap<String, List<Integer>>();  
ArrayList<String> list = new ArrayList<String>();  
Iterator<Map.Entry<String, List<Integer>>> iterator = complexMap.entrySet().iterator();

好在 Java 10 引入了 var 关键字,支持局部变量的类型推断,编译器会根据初始化表达式自动推断变量的类型,让代码可以变得更简洁。

java
var complexMap = new HashMap<String, List<Integer>>();  
var list = new ArrayList<String>();  
var iterator = complexMap.entrySet().iterator();  
  
// 使用 var 的 for-each 循环  
for (var entry : complexMap.entrySet()) {  
    var key = entry.getKey();  
    var value = entry.getValue();  
    // 处理逻辑  
}

但是,var 关键字是一把双刃剑,不是所有程序员都喜欢它。毕竟代码中都是 var,丢失了一定的可读性,尤其是下面这种代码,你不能直观地了解变量的类型:

java
var data = getData();

而且使用 var 时,还要确保编译器能正确推断类型,下面这几种写法都是错误的:

所以我个人其实是没那么喜欢用这⁢个关键字的,纯个人⁡偏好。        ⁡

var 使用注意事项

  1. 只能用于局部变量:不能用于字段、方法参数或返回类型

  2. 必须初始化:声明时必须赋值,让编译器能推断类型

  3. 不能推断 nullvar x = null; 是错误的

  4. 不能推断泛型var list = new ArrayList<>(); 会推断为 ArrayList<Object>

java
public class VarExample {  
    // var field = "错误"; // 不能用于字段  
      
    public void method() {  
        // 正确用法  
        var name = "张三";              // String  
        var age = 25;                  // int  
        var salary = 5000.5;           // double  
        var isActive = true;           // boolean  
        var list = List.of(1, 2, 3);   // List<Integer>  
          
        // 错误用法  
        // var x;                      // 必须初始化  
        // var y = null;               // 不能推断null  
        // var z = () -> {};           // 不能推断lambda  
    }  
      
    // public var getResult() { } // 不能用于返回类型  
    // public void process(var param) { } // 不能用于参数  
}

【了解】应用程序类数据共享

Java 10 扩展了类数据共享功能,允许应用程序类也参与共⁢享(Application Class-⁡Data Sharing)。在此之前,只⁡有 JDK 核心类可以进行类数据共享,应用程序类每次启动都需要重新加载和解析。

类数据共享的核心思路是:将 JDK 核心类和应用程序类的元数据都打包到共享归档文件中,多个 JVM 实例同时映射同一个归档文件,通过 共享读取 优化应用启动时间和减少内存占用。

使用步骤:Ea7H6DxcZeWlVJFFEnFyn3Lx21/mLUEMxr9P/hnm5xs=

  1. 生成类列表
bash
java -XX:DumpLoadedClassList=classes.lst MyApp
  1. 创建归档文件
bash
java -Xshare:dump -XX:SharedClassListFile=classes.lst -XX:SharedArchiveFile=myapp.jsa
  1. 使用归档文件启动
bash
java -Xshare:on -XX:SharedArchiveFile=myapp.jsa MyApp

这个特性主要用于容器化部署和微服务⁢场景,可以显著减少启动⁡时间。        ⁡

【了解】垃圾收集器接口

Java 10 引入了统一的⁢垃圾收集器接口,为⁡不同的 GC 实现⁡提供了标准化的框架。这个改进主要是为了:

  • 简化新 GC 算法的开发和集成

  • 提高代码的可维护性

  • 支持更灵活的 GC 配置

这个特性对普通开发者来说是透明的,⁢主要影响 JVM 内部⁡实现。        ⁡

【了解】G1 的并行完整 GC

在 Java 10 之前,G⁢1 垃圾收集器的 ⁡Full GC 是⁡单线程的,当堆内存不足时性能会很差。

Java 10 改进了 G1⁢ 的 Full G⁡C 实现,使用并行⁡算法:

bash
# 启用 G1 垃圾收集器  
java -XX:+UseG1GC -XX:MaxGCPauseMillis=200 MyApp

并行 Full GC 可以显⁢著减少长时间的停顿⁡,提升应用的响应性⁡。

【了解】线程局部握手

线程局部握手(Thread-Loca⁢l Handshakes⁡)是一个 JVM 内部优⁡化,允许在不停止所有线程的情况下对单个线程执行回调:

  • 减少全局安全点的使用

  • 降低 JVM 操作的延迟

  • 提高整体性能

这个特性对开发者透明,但可以改善 JVM 的整体性能表现。

【了解】在备用内存设备上进行堆分配

Java 10 支持将 JV⁢M 堆分配到非易失⁡性内存(NVM)或⁡其他备用内存设备上:

bash
# 使用备用内存设备  
java -XX:AllocateHeapAt=/mnt/pmem MyApp

这个特性主要用于:

  • 利用大容量持久内存

  • 减少应用重启时的数据重建时间

  • 支持更大的堆内存配置

【了解】根证书

Java 10 在默认的 TrustSt⁢ore 中包含了一组根证书⁡颁发机构(CA)证书,解决⁡了 OpenJDK 构建版本中缺少根证书的问题。

这意味着 OpenJDK 现⁢在可以直接支持 T⁡LS 连接,无需额⁡外配置证书:

java
// 现在可以直接使用 HTTPS 连接  
URL url = new URL("https://www.example.com");  
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();  
// 无需额外的证书配置

【了解】基于时间的版本发布

Java 10 确立了基于时间的发布模式:

  • 每 6 个月发布一个新版本(3月和9月)

  • 每 3 年发布一个 LTS 版本

  • 版本号格式:年份.月份(如 18.3 表示 2018年3月)

这个改变让 Java 的发展⁢更加可预测,新特性⁡能更快地到达开发⁡者手中。

API 改进

【了解】Optional 增强

Optional 类新增了 orElseThrow() 方法,作为 get() 的更好替代:

java
Optional<String> optional = Optional.of("Hello");  
  
// Java 10 新增的方法  
String value1 = optional.orElseThrow(); // 等同于 get(),但语义更清晰  
  
// 相比传统的 get() 方法,orElseThrow() 语义更明确  
String value2 = optional.get(); // 不推荐,语义不清

【了解】Collection 增强

Collection 接口新增了 copyOf() 方法,可以创建不可变的副本:

java
List<String> original = new ArrayList<>();  
original.add("A");  
original.add("B");  
  
// 创建不可变副本  
List<String> copy = List.copyOf(original);  
// copy.add("C"); // 会抛出 UnsupportedOperationException  
  
Set<Integer> originalSet = new HashSet<>();  
originalSet.add(1);  
originalSet.add(2);  
  
Set<Integer> copySet = Set.copyOf(originalSet);

【了解】Collectors 增强

Collectors 类新增了 toUnmodifiableList()toUnmodifiableSet()toUnmodifiableMap() 方法:

java
List<String> names = List.of("张三", "李四", "王五");  
  
// 收集到不可变列表  
List<String> upperNames = names.stream()  
    .map(String::toUpperCase)  
    .collect(Collectors.toUnmodifiableList());  
  
// 收集到不可变集合  
Set<Integer> lengths = names.stream()  
    .map(String::length)  
    .collect(Collectors.toUnmodifiableSet());  
  
// 收集到不可变映射  
Map<String, Integer> nameLength = names.stream()  
    .collect(Collectors.toUnmodifiableMap(  
        name -> name,  
        String::length  
    ));

总结

Java 10 虽然特性不多,但 var 关键字的引入还是很有意义的,让 Java 代码可以更加简洁。应用程序类数据共享和 G1 的改进也为性能优化提供了新的选择。

最重要的是,Java 10 确立了新的发布⁢节奏,为后续版本的快速迭代奠定了⁡基础。虽然不是 LTS ⁡版本,但它标志着 Java 进入了一个新的发展阶段。