Java 12新特性(2019年3月)

正式特性

微基准测试套件

Java 12 引入了 JMH(Java Microbenchmark Harness)作为官方的微基准测试工具:

JMH 可以帮助开发者准确测量代码性能,避免 JT 编译器优化带来的干扰。

默认 CDS 归档

Java 12 默认启用类数据共享(CDS)归档,JDK 安装时会预先创建一个包含常用核心类的归档文件

这可以减少应用启动时间和内存占用。

G1 垃圾收集器改进

Java 12 对 G1 垃圾收集器进行了两项重要改进:

  1. 可中止混合收集:G1 可以在混合收集过程中中止,以满足暂停时间目标

  2. 及时返回未使用内存:G1 可以在空闲时将未使用的堆内存返回给操作系统

String API增强

CompactNumberFormat

Java 12 引入了紧凑数字格式化:

实验特性

Shenandoah 垃圾收集器

Java 12 引入了 Shenandoah Gc 作为实验特性,这是一个低延迟垃圾收集器

Shenandoah 的特点:

  • 低延迟:暂停时间与堆大小无关

  • 并发:大部分工作与应用线程并发执行。

  • 适用性:适合对延迟敏感的应用

预览特性

升级的switch语句

在jdk12之前的switch语句中,如果没有写break,则会出现case穿透现象,下面是对case穿透的一个应用,根据输入的月份打印相应的季节。

在jdk12之后可以省略全部的break和部分case,这样使用

主要改进:

  • 箭头语法:使用 ->避免 fall-through 问题

  • 多标签:case A,B,C->支持多个条件

  • 表达式:可以直接赋值给变量

  • 简洁性:减少样板代码

这个在Java12中是预览功能,如果需要编译和运行的话需要使用下面命令

Java 13新特性(2019年9月)

正式特性

动态 CDS 归档

Java 13 支持在应用运行时动态创建 CDS 归档:

动态 CDS 的优势:

  • 自动化:无需手动分析类加载。

  • 精确性:只包含实际使用的类

  • 便利性:适合复杂的应用场景

ZGC 内存管理改进

Java 13 改进了 ZGC的内存管理,支持取消提交未使用的内存

这个改进让 ZGC 可以

  • 在内存压力小时释放内存

  • 提高系统整体内存利用率

  • 适应动态的内存需求

重新实现传统套接字 API

Java13重新实现了 java.net.Socketjava.net.ServerSocket APl

这个改进对开发者来说是透明的,但为未来的虚拟线程等特性奠定了基础。

String API增强

Files APl 增强

Java 13 为 Files 类添加了mismatch()方法:

预览特性

升级的switch语句(第二次预览)

JDK13中对switch语句又进行了升级,主要引入了 yield 关键字

示例:

yield 关键字用于在代码块中返回值,类似于return,但专用于 switch 表达式。

文本块的变化(预览)

在jdk13之前的版本中如果输入的字符串中有换行的话,需要添加换行符

jdk13之后可以直接这样写:

这样的字符串更加一目了然。

文本块的特点:

  • 三引号语法:使用 """ 包围

  • 保持格式:保留原有的缩进和换行

  • 转义简化:内部的引号不需要转义

特别适合编写

  • HTML/XML内容

  • SQL查询语句

  • JSON 字符串

  • 正则表达式

Java 14新特性(2020年3月)

java 14 新增了很多特性,这里针对较为突出的特性进行说明。jdk12和jdk13中预览版的switch特性,在jdk14中已经是正式的语法了。

正式特性

Switch表达式改进

Java 14 将 Switch 表达式转正了,让条件判断变得更简洁和安全。在这之前,传统的 switch 语句存在不少问题,比如需要手动添加 break 防止穿透、赋值不方便等

Java14后这么写

根据月份判断季节

友好的空指针(NullPointerException)提示

jdk14中添加了对于空指针异常友好的提示,便于开发者快速定位空指针的对象。示例代码:

这个特性需要使用JVM参数启动

垃圾收集器改进

  1. G1 的 NUMA 感知内存分配

Java 14 改进了 G1 垃圾收集器,使其能够感知 NUMA(Non-Uniform Memory Access)架构

这个改进可以

  • 提高多 CPU 系统的内存访问效率

  • 减少跨 NUMA 节点的内存访问

  • 改善大型服务器的性能表现

  1. macOs 和 Windows 上的ZGC

Java 14 将 ZGC 扩展到 macOS 和 Windows 平台

之前 ZGC 只支持 Linux,现在跨平台支持让更多开发者可以体验低延迟 GC。

JFR 事件流

Java 14 引入了 JFR(Java Flight Recorder)事件流 API,允许实时消费 JFR 事件

非易失性映射字节缓冲区

Java 14 支持将 MappedByteBuffer 映射到非易失性内存(NVM)

删除 CMS 垃圾收集器

Java 14 正式移除了 CMS(Concurrent MarkSweep)垃圾收集器

删除 Pack200 工具和 API

Java 14 移除了 Pack200 压缩工具和相关 API

预览特性

instanceof模式匹配

该特性可以减少强制类型转换的操作,简化了代码,代码示例:

record类型

之前在编写Java Bean类的时候,需要编写成员变量,get方法,构造方法,toString方法,hashcode方法,equals方法。这些方法通常会通过开发工具来生成,在jdk14中新增了record类型,通过该类型可以省去这些代码的编写。

jdk14编写User类:

通过反编译命令可以看到该字节码文件中的内容,User类是继承了Record类型:

记录类型有自动生成的成员,包括:

  • 状态描述中的每个组件都有对应的private final字段。

  • 状态描述中的每个组件都有对应的public访问方法。方法的名称与组件名称相同。

  • 一个包含全部组件的公开构造器,用来初始化对应组件。

  • 实现了equals()和hashCode()方法。equals()要求全部组件都必须相等。

  • 实现了toString(),输出全部组件的信息。

Records 还支持自定义方法和验证

文本块(第二次预览)

Java 14 继续完善文本块特性,添加了两个转义序列:

孵化器特性

打包工具(孵化器)

Java 14 引入了 jpackage 工具作为孵化器特性,可以将 Java 应用打包成平台特定的安装包:

外部内存访问 API(孵化器)

Java 14 引入了外部内存访问 API,提供安全高效的堆外内存操作

Java 15新特性(2020年9月)

正式特性

文本块

文本块由预览版变为正式版

文本块会保持代码的缩进、而且内部的引号不需要转义。

配合 String 的格式化方法,就能轻松传入参数生成复杂的字符串模板

文本块的处理方法

Java 15 为文本块提供了几个有用的处理方法

Hidden 隐藏类

Java 15 引入了 Hidden 隐藏类特性,这是一个 专为框架和运行时环境设计 的底层机制,主要是为了优化 动态生成短期类(比如 Lambda 表达式、动态代理)的性能问题,普通开发者无需关心。

在 Lambda 表达式、AOP 动态代理、ORM 映射等场景中,框架会动态生成代码载体(比如方法句柄、临时代理类),这些载体需要关联类的元数据才能运行。如果生成频繁,传统类的元数据会被类加载器追踪,需要等待类加载器卸载才能回收,导致元空间堆积和 GC 压力。

Hidden 类的特点是对其定义类加载器之外的所有代码都不可见,由于不可发现且链接微弱,M 垃圾回收器能够更高效地卸载隐藏类及其元数据,从而防止短期类堆积对元空间造成压力,优化了需要动态生成大量类的性能。

Hidden 类的特点

  1. 不可发现性:不能通过反射 API 发现

  2. 弱链接:与类加载器的连接很弱,便于回收

  3. 访问控制:只能被定义它的类访问

  4. 性能优化:减少元空间压力

Edwards 曲线数字签名算法

Java 15 添加了对 EdDSA(Edwards-curve Digital Signature Algorithm)的支持

EdDSA 的优势

  • 性能更好:比传统的 ECDSA 更快

  • 安全性高:抗侧信道攻击

  • 确定性:相同输入产生相同签名

ZGC 和 Shenandoah 正式化

Java 15 将 ZGC和 Shenandoah 从实验特性升级为正式特性

重新实现传统 DatagramSocket API

Java 15 重新实现了 DatagramSocket 和 MulticastSocket

禁用和弃用偏向锁

偏向锁定的问题

  • 增加了 JVM 复杂性

  • 在现代多线程应用中收益有限

  • 与其他 JVM 特性存在冲突

删除 Nashorn JavaScript 引擎

Java 15 完全移除了 Nashorn JavaScript 引擎

推荐使用独立的 JavaScript引擎,如 GraalVM 的 JavaScript 实现。

预览特性

Sealed Classes(密封类)

密封类和接口,作用是限制一个类可以由哪些子类继承或者实现。

  1. 如果指定模块的话,sealed class和其子类必须在同一个模块下。如果没有指定模块,则需要在同一个包下。

  2. sealed class指定的子类必须直接继承该sealed class。

  3. sealed class的子类要用final修饰。

  4. sealed class的子类如果不想用final修饰的话,可以将子类声明为sealed class。

Animal类,在指定允许继承的子类时可以使用全限定名

Cat类

Dog类

Husky类

Test类

instanceof模式匹配(第二次预览)

record类型(第二次预览)

孵化器特性

外部内存访问 API(第二次孵化器)

Java 15 继续完善外部内存访问 API

Java16新特性(2021年3月)

正式特性

Records

以前,我们如果想创建一个 POJO 对象来存一些数据,需要编写大量的样板代码,包括构造函数、getter 方法、equals、hashCode、toString 等等,比较麻烦。

即使通过 Lombok 插件简化了代码,估计也要十几行。

有了 Java 16 的 Records,创建数据包装类简直不要太简单,一行代码搞定

Records 自动提供了所有必需的方法,使用方式完全一样

此外,Records 还支持自定义方法和验证逻辑,只不过个人建议这种情况下不如老老实实用"类"了。

instanceof 模式匹配

Java 16 正式推出了 instanceof 的模式匹配,让类型检查和转换变得更优雅。

Stream 新增方法

Java 16 为 Stream APl 添加了 tolist()方法,可以用更简洁的代码将流转换为不可变列表。

还提供了 mapMulti()方法,跟 fatMap 的作用一样,将一个元素映射为0个或多个元素,但是某些场景下比 fatMap 更灵活高效。

当需要从一个元素生成多个元素时,fatMap 需要先创建一个中间 Stream,而 mapMulti()可以通过传入的 Consumer 直接“推送" 多个元素,避免了中间集合或 Stream 的创建开销。

mapMulti() 的实际应用

打包工具正式化

Java 16 将jpackage 工具正式化,可以创建平台特定的安装包

Unix 域套接字通道

Java 16 添加了对 Unix 域套接字的支持

Unix 域套接字的优势

  • 性能更好:本地通信无需网络栈

  • 安全性高:基于文件系统权限

  • 可靠性强:不受网络问题影响

Alpine Linux 端囗

Java 16 正式支持 Alpine Linux,这对容器化部署很重要

Alpine Linux 的优势

  • 体积小:基础镜像只有几 MB

  • 安全性高:攻击面小

  • 适合容器:启动快,资源占用少

弹性元空间

Java 16 改进了元空间的内存管理,可以更及时地将未使用的内存返回给操作系统

这个改进可以:

  • 减少长期运行应用的内存占用提高容器环境下的内存利用率

  • 降低内存压力

默认强封装 JDK内部

Java 16 默认强封装 JDK 内部 API,提高安全性

这个改变鼓励开发者

  • 使用标准 API而不是内部 API

  • 迁移到公开的替代方案

  • 提高代码的可移植性

包装类构造方法的警告

使用包装类的构造方法在编译的时候会出现警告,不建议再使用包装类的构造方法。下面代码在javac编译之后会出现警告。

不建议使用包装类作为锁对象,倘若使用包装类作为锁对象,在编译时会出现警告。

新增日时段

在DateTimeFormatter.ofPattern传入B可以获取现在时间对应的日时段,上午,下午等

InvocationHandler新增方法

在该接口中添加了下面方法

该方法可以调用父接口中defalut方法,比如有下面接口

实现类

测试类:

预览特性

密封类(第二次预览)

Java 16 继续完善密封类特性

密封类的实际应用

孵化器特性

向量 API(孵化器)

Java 16 引入了向量 API,可以利用现代 CPU的 SIMD 指令

向量 API的优势

  • 性能提升:利用 SIMD 指令并行计算。

  • 跨平台:JVM 自动选择合适的指令

  • 类型安全:编译时检查向量操作

外部链接器 API(孵化器)

Java 16 引入了外部链接器 API,可以更安全地调用本地代码