知识模块
☕ Java 知识模块
六、Java 新特性
JDK17 新特性

JDK 17 新特性

面试提问

"JDK 17 有哪些重要新特性?密封类是什么?"


JDK 17 简介

JDK 17 是 LTS(长期支持)版本,是 Java 生态的重要里程碑。

从 JDK 11 到 JDK 17 的重要特性

版本重要特性
JDK 12Switch 表达式(预览)
JDK 13文本块(预览)
JDK 14Records(预览)、instanceof 模式匹配(预览)
JDK 15文本块(正式)、密封类(预览)
JDK 16Records(正式)、instanceof 模式匹配(正式)
JDK 17密封类(正式)、Switch 模式匹配(预览)

1. 密封类(Sealed Classes)

概念

密封类限制哪些类可以继承或实现它。

// 密封类声明
public sealed class Shape 
    permits Circle, Rectangle, Triangle {
    
    // 允许的子类必须在同一模块或包中
}
 
// permitted 子类必须是 final、sealed 或 non-sealed
public final class Circle extends Shape {
    private final double radius;
}
 
public final class Rectangle extends Shape {
    private final double width, height;
}
 
public non-sealed class Triangle extends Shape {
    // non-sealed 允许进一步继承
}

使用场景

// 模式匹配中使用
double area(Shape shape) {
    return switch (shape) {
        case Circle c -> Math.PI * c.radius() * c.radius();
        case Rectangle r -> r.width() * r.height();
        case Triangle t -> 0.5 * t.base() * t.height();
    };
}

接口密封

public sealed interface Service permits HttpService, GrpcService {
    void start();
}
 
public final class HttpService implements Service {
    @Override
    public void start() { }
}
 
public final class GrpcService implements Service {
    @Override
    public void start() { }
}

2. instanceof 模式匹配

传统写法

if (obj instanceof String) {
    String s = (String) obj;  // 需要强制转换
    System.out.println(s.length());
}

模式匹配写法

if (obj instanceof String s) {  // 直接声明变量
    System.out.println(s.length());
}
 
// 条件判断
if (obj instanceof String s && s.length() > 5) {
    System.out.println(s.toUpperCase());
}

3. Switch 表达式

传统写法

String dayType;
switch (day) {
    case MONDAY:
    case TUESDAY:
    case WEDNESDAY:
    case THURSDAY:
    case FRIDAY:
        dayType = "工作日";
        break;
    case SATURDAY:
    case SUNDAY:
        dayType = "周末";
        break;
    default:
        dayType = "未知";
}

Switch 表达式写法

// 箭头语法
String dayType = switch (day) {
    case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> "工作日";
    case SATURDAY, SUNDAY -> "周末";
    default -> "未知";
};
 
// 带代码块
String dayType = switch (day) {
    case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> {
        System.out.println("努力工作");
        yield "工作日";  // 使用 yield 返回值
    }
    case SATURDAY, SUNDAY -> "周末";
    default -> "未知";
};

4. 文本块(Text Blocks)

传统写法

String json = "{\n" +
              "  \"name\": \"张三\",\n" +
              "  \"age\": 25\n" +
              "}";

文本块写法

String json = """
    {
        "name": "张三",
        "age": 25
    }
    """;

特性

// 自动去除前导空格(以最左边为准)
String html = """
    <html>
        <body>
            <p>Hello</p>
        </body>
    </html>
    """;
 
// 行尾加 \ 避免换行
String text = """
    这是一段很长的文字,\
    实际上是一行。\
    """;
 
// 使用 %s 占位符
String name = "张三";
String greeting = """
    Hello, %s!
    """.formatted(name);

5. Records(记录类)

传统写法

public class User {
    private final String name;
    private final int age;
    
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    public String getName() { return name; }
    public int getAge() { return age; }
    
    @Override
    public boolean equals(Object o) { ... }
    @Override
    public int hashCode() { ... }
    @Override
    public String toString() { ... }
}

Record 写法

public record User(String name, int age) {
    // 自动生成:构造器、getter、equals、hashCode、toString
}
 
// 使用
User user = new User("张三", 25);
user.name();  // "张三"(注意:不是 getName())
user.age();   // 25

自定义方法

public record User(String name, int age) {
    // 静态字段
    public static final int ADULT_AGE = 18;
    
    // 静态方法
    public static User of(String name, int age) {
        return new User(name, age);
    }
    
    // 实例方法
    public boolean isAdult() {
        return age >= ADULT_AGE;
    }
    
    // 紧凑构造器(验证)
    public User {
        if (age < 0) {
            throw new IllegalArgumentException("年龄不能为负");
        }
    }
}

6. 其他重要特性

随机数生成器增强

// 传统 Random
Random random = new Random();
 
// JDK 17 新 API
RandomGeneratorFactory<RandomGenerator> factory = 
    RandomGeneratorFactory.of("L32X64MixRandom");
RandomGenerator rng = factory.create();
 
// 获取所有算法
RandomGeneratorFactory.all()
    .map(RandomGeneratorFactory::name)
    .forEach(System.out::println);

精简数字格式

// 传统写法
int million = 1000000;
 
// 下划线分隔
int million = 1_000_000;
 
// JDK 17:紧凑数字格式
NumberFormat format = NumberFormat.getCompactNumberInstance(
    Locale.CHINA, NumberFormat.Style.SHORT);
format.format(1000);    // "1千"
format.format(10000);   // "1万"
format.format(1000000); // "100万"

Vector API(孵化)

// SIMD 向量计算
static final VectorSpecies<Float> SPECIES = FloatVector.SPECIES_256;
 
void vectorComputation(float[] a, float[] b, float[] c) {
    for (int i = 0; i < a.length; i += SPECIES.length()) {
        FloatVector va = FloatVector.fromArray(SPECIES, a, i);
        FloatVector vb = FloatVector.fromArray(SPECIES, b, i);
        va.mul(vb).intoArray(c, i);
    }
}

面试要点总结

问题答案要点
密封类?sealed + permits,限制继承
instanceof 模式匹配?if (obj instanceof String s)
Switch 表达式?箭头语法、yield 返回
文本块?三引号 """,多行字符串
Record?自动生成 getter、equals、hashCode、toString

参考资料