Java 17 是 2021 年 9 月发布的长期支持(LTS)版本,带来了许多重要的特性和改进,主要包括:
- Sealed Classes(密封类) 精确控制类的继承关系
- Records(记录类) 简化不可变数据载体的创建
- Pattern Matching for
instanceof(模式匹配) 简化类型判断和转换代码 - Switch Expressions(开关表达式) 支持返回值,更简洁
- Text Blocks(文本块) 多行字符串更优雅
- ZGC 和 Shenandoah GC 低延迟垃圾回收器正式转正
- 其他改进 -
var增强、StreamAPI 优化、UTF-8 作为默认编码等 - RandomGenerator 增强的伪随机数生成器
- NullPointerException 增强的空指针异常信息
1. Sealed Classes(密封类)
什么是密封类?
密封类允许精确控制哪些类可以继承它,防止意外的继承和扩展,提高代码的安全性和可维护性。
使用场景
- 设计一个类层次结构,并且希望只允许特定的子类继承时。
代码结构

代码示例
scala
/**
* 功能描述: 密封类 前期指定哪些类可以继承
*
* @author Songxianyang
* @date 2025/11/19 16:32
*/
public sealed class Parent permits Sub1, Sub2 {
}
/**
* 功能描述:子类必须是 final 或 sealed
* sealed:子类也可以是密封的,继续限制继承
*
* @author Songxianyang
* @date 2025/11/19 16:33
*/
public final class Sub1 extends Parent {
}
/**
* 功能描述: 子类也可以是密封的,继续限制继承
*
* @author Songxianyang
* @date 2025/11/19 16:33
*/
public sealed class Sub2 extends Parent permits Sub2_1 {
}
/**
* 功能描述:
*
* @author Songxianyang
* @date 2025/11/19 16:37
*/
public final class Sub2_1 extends Sub2 {
}
/**
* 功能描述: 子类也可以是密封的,继续限制继承
* 提示:'Sub3' is not allowed in the sealed hierarchy
* @author Songxianyang
* @date 2025/11/19 16:33
*/
// public final class Sub3 extends Parent {
// }
运行结果图
无

2. Records(记录类)
什么是记录类?
record 是一种不可变的数据载体,用于简洁地创建"数据容器"类(如 DTO、VO),自动生成 equals()、hashCode()、toString() 和访问器方法。
使用场景
- 需要一个简单的类来存储数据,不需要复杂的业务逻辑时。
代码示例
csharp
public record Cat(String name, String id) {
}
/**
* 功能描述:操作纪录类
*
* @author Songxianyang
* @date 2025/11/19 16:53
*/
public class Main {
public static void main(String[] args) {
Cat cat = new Cat("小猫", "1111");
// 记录类的字段是 final 的,不能修改
System.out.println(cat.id());
System.out.println(cat.name());
System.out.println(cat);
System.out.println(cat.hashCode());//25070276
Cat cat1 = new Cat("小猫", "1111");
System.out.println(cat1.hashCode());//25070276
// equals==true
}
}
运行结果图

3. Pattern Matching for instanceof 模式匹配
什么是模式匹配?
简化了 instanceof 的判断和类型转换流程,直接在 instanceof 表达式中声明变量,避免冗余代码。
使用场景
- 需要判断一个对象的类型,并进行强制转换时。
代码示例
typescript
/**
* 功能描述:
*
* @author Songxianyang
* @date 2025/11/19 17:13
*/
public class Main {
public static void main(String[] args) {
String name = "AAA";
old(name);
new0(name);
}
/**
* 老式写法
* @param obj
*/
private static void old(Object obj) {
if (obj instanceof String){
String s= (String)obj;
System.out.println(s.toLowerCase(Locale.ROOT));
}
if (obj instanceof Integer){
Integer i= (Integer)obj;
System.out.println(i*2);
}
}
/**
* 新写法
* 节省代码
* @param obj
*/
private static void new0(Object obj) {
if (obj instanceof String s){
System.out.println(s.toLowerCase(Locale.ROOT));
}
if (obj instanceof Integer i){
System.out.println(i*2);
}
}
}
运行结果图

4. Switch Expressions
什么是 Switch 表达式?
switch 语句可以作为表达式使用,直接返回值,并且支持 -> 语法,简化代码结构。
使用场景
- 需要根据条件返回不同的值时。
- 根据类型计算结果、映射枚举值等。
代码示例
typescript
/**
* 功能描述:
*
* @author Songxianyang
* @date 2025/11/19 17:44
*/
public class Main {
public static void main(String[] args) {
Integer day = 2;
System.out.println(getDayOfWeekNew(day));
System.out.println(getDayOfWeekOld(day));
}
private static String getDayOfWeekOld(Integer i){
String res = "";
switch (i){
case 1: res="Monday"; break;
case 2: res="Tuesday"; break;
default: res="未知"; break;
}
return res;
}
private static String getDayOfWeekNew(Integer i){
return switch (i){
case 1 -> "Monday";
case 2 -> "Tuesday";
default -> "未知";
};
}
}
运行结果图

5. Text Blocks(文本块)
什么是文本块?
用于创建多行字符串,避免手动添加换行符和转义字符,让代码更清晰。
使用场景
- 需要定义多行字符串时。
- SQL 查询语句、JSON 数据等。
代码示例
swift
/**
* 功能描述:
*
* @author Songxianyang
* @date 2025/11/21 11:15
*/
public class Main {
public static void main(String[] args) {
String old="SELECT\n" +
"\t`Host`,`User`,\n" +
"\tSelect_priv,\n" +
"\tShow_db_priv,\n" +
"\tShow_view_priv \n" +
"FROM\n" +
"\t`user`;";
String new1= """
SELECT
`Host`,`User`,
Select_priv,
Show_db_priv,
Show_view_priv
FROM
`user`;
""";
System.out.println(old);
System.out.println("---------------");
System.out.println(new1);
}
}
运行结果图

6. ZGC 和 Shenandoah GC
什么是 ZGC / Shenandoah GC?
- ZGC:低延迟垃圾回收器,目标是将 GC 停顿时间控制在毫秒级别,适合对响应时间要求高的应用。
- Shenandoah GC:同样是低延迟 GC,通过并发压缩技术减少停顿时间。
启用方式
在 JVM 启动参数中指定:
ruby
# 使用 ZGC
java -XX:+UseZGC -jar your-app.jar
# 使用 Shenandoah GC
java -XX:+UseShenandoahGC -jar your-app.jar
7. 其他重要改进
var 关键字增强、toList() 方法
var 可以用于 lambda 表达式的参数类型推断、新增 toList() 方法,更方便地将流转换为列表。
scss
/**
* 功能描述:
*
* @author Songxianyang
* @date 2025/11/21 11:27
*/
public class Main {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3);
System.out.println("Java 17 之前");
list.forEach((Integer s) -> System.out.println(s));
System.out.println("Java 17 之后");
list.forEach((var s)-> System.out.println(s));
System.out.println("本人常用");
list.forEach(s-> System.out.println(s));
System.out.println("---------------------");
// 更方便地将流转换为列表
List<Integer> collectOld = list.stream().filter(i -> i > 1).collect(Collectors.toList());
System.out.println(collectOld);
// 替代 collect(Collectors.toList())
List<Integer> collectNew = list.stream().filter(i -> i > 1).toList();
System.out.println(collectNew);
}
}
运行结果图

8.RandomGenerator 增强的伪随机数生成器
使用示例
java
/**
* 标准随机数生成算法名称常量
*/
public final class RandomGeneratorConstants {
private RandomGeneratorConstants() {} // 防止实例化
// JDK 17+ 标准算法
public static final String L32X64_MIX_RANDOM = "L32X64MixRandom";
public static final String XOROSHIRO_128_PLUS_PLUS = "Xoroshiro128PlusPlus";
public static final String XOSHIRO_256_PLUS_PLUS = "Xoshiro256PlusPlus";
public static final String L64X128_MIX_RANDOM = "L64X128MixRandom";
public static final String L64X128_STAR_STAR_RANDOM = "L64X128StarStarRandom";
public static final String L64X256_MIX_RANDOM = "L64X256MixRandom";
public static final String L128X128_MIX_RANDOM = "L128X128MixRandom";
public static final String L128X256_MIX_RANDOM = "L128X256MixRandom";
// 传统/安全算法
public static final String SECURE_RANDOM = "SecureRandom";
public static final String LEGACY_RANDOM = "Random"; // java.util.Random
public static final String SPLITTABLE_RANDOM = "SplittableRandom";
// 获取默认算法(JDK 17+ 默认是 L32X64MixRandom)
public static RandomGenerator getDefault() {
return RandomGenerator.getDefault();
}
}
/**
* 功能描述: 随机数生成
*
* @author Songxianyang
* @date 2025/11/21 15:34
*/
public class Main {
public static void main(String[] args) {
RandomGenerator generator = RandomGenerator.of(L64X128_MIX_RANDOM);
System.out.println("随机生成整数:"+generator.nextInt());
System.out.println("随机生成小数:"+generator.nextInt());
System.out.println("随机生成范围内的随机数 0-100");
int nextInt = generator.nextInt(0, 100);
System.out.println(nextInt);
}
}
运行结果图

9.NullPointerException 增强的空指针异常信息
使用示例:
typescript
/**
* 功能描述:
*
* @author Songxianyang
* @date 2025/11/21 16:46
*/
public class Main {
static class Person {
String name;
Address address;
// getters and setters
public String getName() { return name; }
public Address getAddress() { return address; }
}
static class Address {
String id;
String city;
public String getStreet() { return id; }
public String getCity() { return city; }
}
/**
* 以前的异常
* Exception in thread "main" java.lang.NullPointerException
* at Main.main(Main.java:48)
* 现在的异常:Java17中展示更详细的异常。
* Exception in thread "main" java.lang.NullPointerException: Cannot invoke "nullpointer.Main$Address.getCity()" because the return value of "nullpointer.Main$Person.getAddress()" is null
* at nullpointer.Main.main(Main.java:48)
* @param args
*/
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.getAddress().getCity());
}
}
运行结果图
