JDK17新特性【附源码】

JDK 17(Java SE 17)是 2021 年 9 月发布的长期支持(LTS)版本,汇总了 JDK 11 到 JDK 17 之间的多项重要更新,在语言特性、性能、安全性和兼容性上均有显著提升。以下是 JDK 17 的主要新特性及重要特性的代码示例:

一、主要新特性列表

  1. 密封类(Sealed Classes):限制类的继承关系,仅允许指定的子类继承
  2. 模式匹配的instanceof(Pattern Matching for instanceof:简化类型判断与转换,减少冗余代码
  3. 增强的switch表达式(Enhanced switch:支持箭头语法、yield返回值,且可匹配模式(如类型模式)
  4. 记录类(Records):简化不可变数据载体类的定义(JDK 16 正式引入,JDK 17 中稳定)
  5. 外部函数与内存 API(Foreign Function & Memory API):预览特性,提供安全高效的本地代码调用和内存访问(替代 JNI)
  6. 向量 API(Vector API):第二次孵化,支持硬件加速的向量计算,提升数值处理性能
  7. 移除实验性的 AOT 和 JIT 编译器:移除 JDK 9 引入的实验性 AOT( Ahead-of-Time)编译和 JIT(Just-In-Time)编译器
  8. 强封装 JDK 内部 API:默认强封装jdk.internal.*等内部 API,仅开放少数关键 API,增强安全性
  9. 弃用 Security Manager:标记SecurityManager为弃用,准备未来移除(曾用于沙箱安全,现已被更现代的安全机制替代)
  10. 移除 Applet API:彻底移除早已过时的 Applet 相关类(java.applet包)
  11. ZGC 和 Shenandoah 垃圾收集器转正:ZGC(低延迟)和 Shenandoah(低暂停)从实验性变为正式特性
  12. 其他改进:如java.util.random包新增随机数生成器、String类新增indent()方法等

二、重要特性及代码示例

1. 密封类(Sealed Classes)

密封类通过sealed关键字声明,限制只有指定的子类(permits关键字指定)可以继承它,避免类被无限制扩展,增强代码的可维护性。

示例:密封类与允许的子类

// 密封类:仅允许Student和Teacher继承
public sealed class Person permits Student, Teacher {
    protected String name;
    
    public Person(String name) {
        this.name = name;
    }
    
    public abstract String getRole();
}

// 允许的子类:可以是final(不可再继承)或non-sealed(可继续继承)
public final class Student extends Person {
    private String studentId;
    
    public Student(String name, String studentId) {
        super(name);
        this.studentId = studentId;
    }
    
    @Override
    public String getRole() {
        return "Student";
    }
}

// 允许的子类:non-sealed表示可被其他类继承
public non-sealed class Teacher extends Person {
    private String subject;
    
    public Teacher(String name, String subject) {
        super(name);
        this.subject = subject;
    }
    
    @Override
    public String getRole() {
        return "Teacher";
    }
}

// 错误:不允许继承密封类Person(未在permits中声明)
// public class Staff extends Person { ... } // 编译报错
2. 模式匹配的instanceof

传统instanceof需要先判断类型,再强制转换,代码冗余。JDK 17 中,instanceof可直接绑定变量,自动完成转换,简化逻辑。

示例:模式匹配简化类型处理

public class PatternMatchingExample {
    public static void main(String[] args) {
        Object obj = "Hello, JDK 17";
        
        // 传统方式:判断后需手动转换
        if (obj instanceof String) {
            String s = (String) obj; // 冗余转换
            System.out.println("长度:" + s.length());
        }
        
        // JDK 17:模式匹配,直接绑定变量s(自动转换)
        if (obj instanceof String s) {
            System.out.println("长度:" + s.length()); // 直接使用s,无需转换
        }
        
        // 结合条件判断
        if (obj instanceof String s && s.length() > 5) {
            System.out.println("长字符串:" + s); // 输出:长字符串:Hello, JDK 17
        }
    }
}
3. 增强的switch表达式

JDK 17 的switch支持:

  • 箭头语法(->):简化分支逻辑,无需break
  • yield关键字:返回分支结果
  • 模式匹配:可根据类型、枚举等模式匹配分支

示例:switch的模式匹配与箭头语法

public class EnhancedSwitchExample {
    public static String format(Object obj) {
        // 基于类型模式的switch(匹配obj的实际类型)
        return switch (obj) {
            case Integer i -> String.format("整数:%d", i);
            case String s -> String.format("字符串:%s", s);
            case Double d -> String.format("小数:%.2f", d);
            // 多个常量合并(如null和默认情况)
            case null, default -> "未知类型";
        };
    }
    
    public static void main(String[] args) {
        System.out.println(format(100));    // 输出:整数:100
        System.out.println(format("test")); // 输出:字符串:test
        System.out.println(format(3.1415)); // 输出:小数:3.14
        System.out.println(format(null));   // 输出:未知类型
    }
}
4. 记录类(Records)

记录类(record)是不可变数据载体类的简化语法,自动生成equals()hashCode()toString()和字段访问方法,无需手动编写。

示例:记录类替代传统数据类

// 记录类:自动包含name和age字段,及相关方法
public record User(String name, int age) {
    // 可自定义构造器(需调用默认构造器)
    public User {
        if (age < 0) {
            throw new IllegalArgumentException("年龄不能为负数");
        }
    }
    
    // 可添加额外方法
    public String getGreeting() {
        return "Hello, " + name;
    }
}

public class RecordExample {
    public static void main(String[] args) {
        User user = new User("Alice", 30);
        System.out.println(user.name()); // 自动生成的访问方法
        System.out.println(user.age());
        System.out.println(user); // 自动生成的toString():User[name=Alice, age=30]
        
        User user2 = new User("Alice", 30);
        System.out.println(user.equals(user2)); // 自动生成的equals():true
    }
}
5. 外部函数与内存 API(预览)

该 API 允许 Java 安全地调用本地代码(如 C 语言库)和访问本地内存,替代复杂且不安全的 JNI(Java Native Interface)。

示例:调用本地strlen函数计算字符串长度

import java.lang.foreign.*;
import java.lang.invoke.MethodHandle;
import static java.lang.foreign.ValueLayout.ADDRESS;
import static java.lang.foreign.ValueLayout.JAVA_LONG;

public class ForeignFunctionExample {
    public static void main(String[] args) throws Throwable {
        // 加载C标准库(不同系统路径可能不同,如Windows为"msvcrt.dll")
        try (Arena arena = Arena.ofConfined()) { // 内存 arena 管理本地内存
            // 查找本地函数"strlen"(计算字符串长度)
            SymbolLookup stdlib = SymbolLookup.loaderLookup();
            MethodHandle strlen = Linker.nativeLinker()
                .downcallHandle(
                    stdlib.find("strlen").orElseThrow(),
                    FunctionDescriptor.of(JAVA_LONG, ADDRESS) // 函数签名:long strlen(char*)
                );
            
            // 分配本地内存并存储字符串
            MemorySegment str = arena.allocateFrom("Hello");
            
            // 调用本地函数strlen
            long length = (long) strlen.invoke(str);
            System.out.println("字符串长度:" + length); // 输出:5
        }
    }
}
6. 向量 API(第二次孵化)

向量 API 提供了一种与平台无关的方式编写向量计算代码,可被 JVM 优化为硬件特定的向量指令(如 AVX、SSE),显著提升数值计算性能(如图像处理、科学计算)。

示例:向量计算加速数组元素相加

import jdk.incubator.vector.*;

public class VectorExample {
    private static final VectorSpecies<Float> SPECIES = FloatVector.SPECIES_256;
    
    // 向量加速的数组相加
    public static void vectorAdd(float[] a, float[] b, float[] c) {
        int i = 0;
        int upperBound = SPECIES.loopBound(a.length);
        // 向量批量处理
        for (; i < upperBound; i += SPECIES.length()) {
            FloatVector va = FloatVector.fromArray(SPECIES, a, i);
            FloatVector vb = FloatVector.fromArray(SPECIES, b, i);
            va.add(vb).intoArray(c, i); // 向量相加并写入结果数组
        }
        // 处理剩余元素(非向量批量部分)
        for (; i < a.length; i++) {
            c[i] = a[i] + b[i];
        }
    }
    
    public static void main(String[] args) {
        float[] a = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f};
        float[] b = {6.0f, 7.0f, 8.0f, 9.0f, 10.0f};
        float[] c = new float[5];
        
        vectorAdd(a, b, c);
        for (float val : c) {
            System.out.print(val + " "); // 输出:7.0 9.0 11.0 13.0 15.0
        }
    }
}

总结

JDK 17 作为 LTS 版本,聚焦于提升开发效率和运行时性能:密封类和模式匹配增强了代码的可读性和安全性;记录类简化了不可变数据类的定义;外部函数与内存 API 和向量 API 为高性能场景提供了新工具;ZGC 和 Shenandoah 的转正满足了低延迟应用的需求。这些特性使 JDK 17 成为企业级应用的理想选择,同时保持了对旧版本的良好兼容性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值