Java17的主要新特性总结

概述

JDK 17 于 2021 年 9 月 14 日正式发布。

JDK 17 是自 2018 年JDK 11后的第二个长期支持版本,支持到 2029 年 9 月,支持时间长达8年。下一个长期支持版本是 JDK 21,时间为2023 年 9 月,这次长期支持版本发布计划改了,不再是原来的 3 年一次,而是改成了 2 年一次!非长期支持版本还是半年发一次不变。

JDK 17二进制文件在Oracle免费条款和条件许可下,可以在生产中免费使用(参考:Oracle Releases Java 17),也可以免费重新分发。开源协议为NFTC(Oracle No-Fee Terms and Conditions )。

imageabcd43e5a0924eb1.png

Java 17及以后的版本可以免费使用了,包括商用,更详细的条款可以阅读:Oracle No-Fee Terms and Conditions (NFTC) License Agreement

Java的商用收费始于Java 82019年1月份开始,Oracle JDK开始对Java SE 8之后的版本开始进行商用收费,确切的说是8u201/202之后的版本。如果你用 Java 开发的功能如果是用作商业用途的,如果还不想花钱购买的话,能免费使用的最新版本是8u201/202。当然如果是个人客户端或者个人开发者可以免费试用 Oracle JDK所有的版本。另外Oracle官方其实还提供了一个完全免费开源的JDK版本—— Open JDK,这是免费使用的。中间版本

商用收费情况

Java的商用收费始于Java 8Oracle JDK宣布从2019年1月份开始对Java SE 8之后的版本开始进行商用收费,确切的说是8u201/202之后的版本。如果你用 Java 开发的功能如果是用作商业用途的,如果还不想花钱购买的话,能免费使用的最新版本是8u201/202。当然如果是个人客户端或者个人开发者可以免费试用 Oracle JDK所有的版本。另外Oracle官方其实还提供了一个完全免费开源的JDK版本—— Open JDK,这是免费使用的。

决定是否收费首先得看JDK使用的是什么协议?

  • BCL协议:即Oracle Binary Code License Agreement,协议规定你可以使用JDK,但是不能进行修改。私用和商用都可以,但是JDK中的某些商业特性,是需要付费才可以使用的。

  • OTN协议:即Oracle Technology Network License Agreement,目前新发布的JDK用的都是这个协议,可以私用,商用需要付费。

版本说明
  • Java 8 以下版本,仍可免费使用。

  • Java 8 (LTS) 部分免费,8u201/202及之前的版本是免费的,之后的商用收费。

  • Java 9 是免费的,过渡版本且不再更新不建议使用。

  • Java 10 是免费的,过渡版本且不再更新不建议使用。

  • Java 11 (LTS) 开始Oracle JDK商用收费,同时提供免费版的Open JDK下载地址

  • Java 12Java 13Java 14Java 15Java 16,全版本商用收费。

  • Java 17 (LTS) 开始,再次可以免费使用。

  • 免费的JDK有 OpenJDKAdoptOpenJDKAmazon CorrettoAzul ZuluBellSoftIBMjClarityRed HatSAP阿里巴巴 Dragonwell等。

JEP(Java Enhancement Proposal)Java增强提案

CSR(Compatibility & Specification Review) 兼容性和规范审查

变动说明

官网:

Java Platform, Standard Edition Java Language Updates, Release 17

JDK 17 Release Notes, Important Changes, and Information

JDK 17

https://blogs.oracle.com/java/post/the-arrival-of-java-17

更多参考:

JDK 17 Documentation - Home 更多版本:Java Platform, Standard Edition Documentation - Releases

Java Platform, Standard Edition Oracle JDK Migration Guide, Release 17

重要变更和信息

JDK 17 包含 14 个 新特性 ,分别为:

而其中与开发过程中直接相关的特性主要包括:JEP 406(Switch 表达式的模式匹配)、JEP 409(密封的类和接口)等。

下载地址

你可以从这个链接下载Oracle JDK版本,更多版本下载

也可以从这个链接下载生产就绪的OpenJDK版本。文件为压缩包,解压并设置环境变量就可以使用。

Java17新特性总结

1、JEP 409:密封的类和接口(正式特性)

JEP 409

功能进化
Java版本特性类型JEP特性
Java 15预览特性JEP 360引入了密封类作为预览特性。
Java 16预览特性JEP 397第二次预览
Java 17正式特性JEP 409成为正式特性

密封的类和接口限制了哪些其他类或接口可以扩展或实现它们。

继承,作为面向对象语言的三大特性之一,我们工作过程中经常使用,可以重写父类的方法。我们可以通过继承(extend)来实现类的能力复用、扩展与增强。但有的时候,有些能力我们不希望被继承了去做一些不可预知的扩展。所以,我们需要对继承关系有一些限制的控制手段。而密封类的作用就是限制类的继承

通常开发项目时,我们会先将接口提供出来,然后根据情况给出不同的基础实现类,子类再基础这些基础实现类进行扩展,我们可能并不希望子类直接继承接口,当然直接继承接口的写法从代码上看没有任何问题,但存在安全隐患。一般我们会通过开发约束对,这样的情况说一些要求,但是这样并不能杜绝这类问题。

限制手段

对于继承能力的控制,目前主要通过下面两种方式控制:

  1. final修饰类,这样类就无法被继承了

  2. 无修饰词修饰的类(即去掉public修饰符,一般类修饰符是public),可以限制该类只能被同一个包下的类继承。

这两种限制方式的粒度都非常粗,对于一些要求比较细致的场景,是无法满足的。

密封类

为了进一步增强继承的限制能力,Java 15 引入密封类来精确控制类的继承问题 ,目前版本为预览特性。

什么是密封类

密封类的主要目的是提供一种更加精确地控制类继承的方法,通过这种方式,类的设计者可以指定一个类它能够被哪些类继承,它增强了类的封装性和安全性。由于密封类限制了类的继承,所以它使得代码更加可预测和易于维护。

  • 密封类(接口)用 sealed 修饰,则它的所有子类都必须在同一个模块或者包内,并且这些子类必须被显式地声明为该密封类的直接子类。

  • 密封类(接口)的子类可以被声明为non-sealed(非密封的)或final(最终的)。non-sealed的子类可以被进一步继承,而final的子类则不能。

  • 密封类(接口)使用 permits 来指定它的子类。

示例代码

这里我们以诗人为例,简化一下,我们这里只讨论汉朝诗人、唐朝诗人、宋朝诗人,代码如下:

 // 诗人基类
 public class Poet {
 }
 ​
 // 汉朝诗人
 public class HanPoet extends Hero{
 }
 // 唐朝诗人
 public class TangPoet extends Poet{
 }
 ​
 // 宋朝诗人
 public class SongPoet extends Hero{
 }
 ​

接下来我们每个类别下面定义2个诗人:

  • 汉朝诗人(HanPoet):司马相如(SiMaXiangRu)、班固(BanGu)、

  • 唐朝诗人(TangPoet):李白(Libai)、杜甫(DuFu)

  • 宋朝诗人(SongPoet):苏轼(SuShi)、陆游(LuYou)

其中李白(Libai)继承自唐朝诗人(TangPoet),我们可以为唐朝诗人做一些公共处理,比如朝代是唐朝,但是有没有这种可能,有程序猿把李白的父类定义为诗人(Poet),那么我们为唐朝诗人定义的那些处理,李白就需要全部重新实现。这显然破坏了继承的实用性。

  • 使用 sealed 修饰Poetpermits 限定子类为: HanPoetTangPoetSongPoet ,只允许这3个类继承,如下:

 // 英雄基类,限制子类为:汉朝诗人(HanPoet)、唐朝诗人(TangPoet)、宋朝诗人(SongPoet)
 public sealed class Poet permits HanPoet,TangPoet,SongPoet {
 }
  • 第二层基类,继续使用 sealed 修饰

 // 汉朝诗人,限制子类为:司马相如(SiMaXiangRu)、班固(BanGu)
 public sealed class HanPoet extends Hero permits SiMaXiangRu,BanGu{
 }
 ​
 // 唐朝诗人,限制子类为:李白(Libai)、杜甫(DuFu)
 public sealed class TangPoet extends Hero permits Libai,DuFu{
 }
 ​
 // 宋朝诗人,限制子类为:苏轼(SuShi)、陆游(LuYou)
 public sealed class SongPoet extends Hero permits SuShi,LuYou{
 }
  • 第三层为具体诗人,他们继承第二层的诗人类型,使用extends继承即可,同时需要表示为non-sealedfinal,由于我们不希望类再往下了,所以定义为 final

 public final class SiMaXiangRu extends HanPoet{
 }
 ​
 public final class Libai extends TangPoet{
 }
 ​
 public final class SuShi extends SongPoet{
 }

这样,子类就不能随便继承父类了。

2、JEP 406: Switch 的模式匹配(预览特性)

JEP 406specification

这是一个预览特性

功能进化

switch功能进化

java版本特性类型JEP特性
Java 5首次引入,仅支持整型数据类型(如 byte, short, char, 和 int)及枚举类型
Java 7支持 String 类型
Java 12预览特性JEP 325支持Switch表达式(箭头函数)
Java 13预览特性JEP 354加入 yield 语句来替代 break 语句,用于从 switch 表达式返回值
Java 14正式特性JEP 361前2个版本的新特性转为正式特性
Java 17预览特性JEP 406引入Switch的模式匹配作为预览特性

在 Java 16 中, JEP 394instanceof的模式匹配发布为正式属性。虽然可以不需要强制转换了,但是仍然需要大量的 if...else。而 Switch 表达式虽然简化了if...else,但是它无法像instanceof一样不需要强制转换。为了解决这个痛点,Java 17引入模式匹配的Switch表达式特性 ,目前该特性为预览特性。

该特性扩展了 switch 表达式和语句,允许它们使用模式匹配,这就意味着我们可以在 switch 的 case 标签中使用模式,如类型模式,使得代码更加灵活和表达性更强。而且也无需进行显式的类型转换了。例如,可以使用 case Integer i 这样的语法来匹配并自动转换类型。

但是,不知道小伙伴们注意没有,Switch 表达式只有一种类型,比如:我有一个诗人类(Poet),它有3个实现类:唐朝诗人(TangPoet)、宋朝诗人(SongPoet)、汉朝诗人(HanPoet),我要根据诗人的类型进行不同处理 :

 Poet poet = ... // 诗人
 ​
 switch (poet.getClass().getName()) {
     case "my.poet.TangPoet":
         TangPoet tp = (TangPoet) obj;
         // 处理唐朝诗人
         break;
     case "my.poet.SongPoet":
         SongPoet sp = (SongPoet) obj;
         // 处理宋朝诗人
         break;
     case "my.poet.HanPoet":
         HanPoet hp = (HanPoet) obj;
         // 处理汉朝诗人
         break;
     // 其他类型
 }

这个强转显然比较麻烦。所以,参考Java 17中,参考instanceof的模式匹配,为switch表达式引入了模式匹配功能作为预览特性。

Switch 模式匹配

在 Java 17 中,switch 表达式允许使用模式匹配来处理对象类型,这样就可以直接在 switch 语句中检查和转换类型,而不需要额外的 if...else 结构和显式类型转换。

case后面可以跟的标签主要有:

  • 类型标签

  • null标签

  • 守卫标签

  • enum或常量值

类型标签

允许在 switch 语句的 case 分支中直接匹配对象的类型。例如,case String s 允许你在该分支中直接作为字符串类型的 s 来使用,避免了显式的类型检查和强制类型转换。

举个例子:

 @Test
 public void switchTest() {
     // 不是用switch根据类型判断
     Object[] objects = { "Hello", "Java", "17", 666, 0.618 };
     for (Object obj : objects) {
         if (obj instanceof Integer v) {
             System.out.printf("为整型 :%s %n", v);
         } else if (obj instanceof Float v) {
             System.out.printf("为Float:%s %n", v);
         } else if (obj instanceof Double v) {
             System.out.printf("为Double:%s %n", v);
         } else if (obj instanceof String v) {
             System.out.printf("为字符串:%s %n", v);
         } else {
             System.out.printf("其他类型:%s %n", obj);
         }
     }
 }

我们用 Switch 表达式来改造下:

 @Test
 public void switchTest() {
     Object[] objects = { "Hello", 123, "World", "Java", 3.14, "skjava" };
     for (Object obj: objects) {
         switch (obj) {
             case Integer v -> System.out.println("为整数型:" + v);
             case Float v -> System.out.println("为浮点型:" + v);
             case Double v -> System.out.println("为双精度浮点数:" + v);
             case String v -> System.out.println("为字符串:" + v);
             default -> System.out.println("其他类型:" + obj);
         }
     }
 }

相比上面的 if...else 简洁了很多。同时在 Java 17之前,Switch选择器表达式只支持特定类型,即基本整型数据类型byteshortcharint;对应的装箱形式ByteShortCharacterIntegerString类;枚举类型。现在有了类型模式,Switch 表达式可以是任何类型啦。

null标签

switch允许任何引用类型的选择器表达式,那么我们需要留意null的情况,在Java17之前,向switch语句传递一个null值,会抛出一个NullPointerException,现在可以通过类型模式,将 null 检查作为一个单独的case标签来处理,如下:

 @Test
 public void switchTest() {
     Object[] objects = { "Hello", "Java", "17", 142857, 0.618 };
     for (Object obj: objects) {
         switch (obj) {
             case Integer v -> System.out.println("为整数型:" + v);
             case Float v -> System.out.println("为浮点型:" + v);
             case Double v -> System.out.println("为双精度浮点数:" + v);
             case String v -> System.out.println("为字符串:" + v);
             case null -> System.out.println("为空值");
             default -> System.out.println("其他类型:" + obj);
         }
     }
 }

case null 可以直接匹配值为 null 的情况。

守卫标签

与匹配常量值的case标签不同,模式case标签可以对应多个变量值。这通常会导致switch规则右侧出现条件语句。

根据字符串长度判断诗句是五言绝句还是七言绝句,代码如下:

@Test
public void switchCaseCaseTest() {
    String[] poems = { "千山鸟飞绝", "春城无处不飞花", "红豆生南国", "二月春风似剪刀","念奴娇" };
    for (String poem : poems) {
        switch (poem) {
            case null -> System.out.println("为空值");
            case String s -> {
                if (s.length() == 5)
                    System.out.printf("五言绝句:%s%n", s);
                else if (s.length() == 7)
                    System.out.printf("七言绝句:%s%n", s);
                else
                    System.out.printf("不知道是啥:%s%n", s);
            }
        }
    }
}

这里的问题是,使用单一模式(即类型)来区分case就只能判断一种情况。我们只能在模式匹配中再通过if……else判断来区分不同的情况,来对一个模式的细化。这时,我们可以是使用switch中的when子句指定模式case标签的条件,例如,case String s when if (s.length() == 5)。表示当类型为String并且字符串长度为5的时候,我们将这种case标签称为守卫case标签,将布尔表达式称为保护。

@Test
public void switchCaseCaseTest() {
    String[] poems = { "千山鸟飞绝", "春城无处不飞花", "红豆生南国", "二月春风似剪刀","念奴娇" };
    for (String poem : poems) {
        switch (poem) {
            case null -> System.out.println("为空值");
            case String s when s.length() == 5 -> System.out.printf("五言绝句:%s%n", s);
            case String s when s.length() == 7 -> System.out.printf("七言绝句:%s%n", s);
            case String s -> System.out.printf("不知道是啥:%s%n", s); //剩余情况,仍然走这个
        }
    }
}

使用守卫标签,我们可以编写更灵活和表达性强的代码。

3、JEP 306:恢复始终执行严格模式的浮点定义

JEP 306

Java 最初只有严格的浮点语义,但从JDK 1.2开始,为了适应当时硬件架构的限制,默认情况下允许这些严格语义中的细微变化,而现在这些都没有必要了。

4、JEP 356:增强型伪随机数生成器。

JEP 356

为伪随机数生成器 (PRNG) 提供新的接口类型和实现。

Java 17 之前的随机数生成

在 Java 17 之前,Java 的随机数生成主要依赖于下面两个核心类:

  • java.util.Random

  • java.security.SecureRandom

Random

该类是最最基本的伪随机数生成器,它用于生成一系列不完全是真正随机的数字。Random 提供了多种方法来生成不同类型的随机数,包括整数、长整数、浮点数等。

  • 生成随机整数

Random rand = new Random();
int randomInt = rand.nextInt(50); // 生成一个0到49之间的随机整数
  • 生成随机浮点数

Random rand = new Random();
double randomDouble = rand.nextDouble(); // 生成一个0.0到1.0之间的随机浮点数

java.util.Random 使用起来很简单,但是它有两个很明显的缺陷。

  1. 具备可观测性:如果知道种子和算法,完全可以生成相同的随机序列。这在需要高安全性的随机数生成(如加密)时是不合适的。不是真的随机。

  2. 线程不安全:在多线程环境下,多个线程共享一个 Random 实例可能导致竞争条件和数据不一致。

ThreadLocalRandom

ThreadLocalRandom 是一个适用于多线程环境下生成随机数的生成器,它通过为每个线程提供一个独立的随机数生成器实例来解决线程安全问题。

ThreadLocalRandom 使用线程局部变量(Thread-Local)的概念,每个线程访问 ThreadLocalRandom 时,实际上是访问它自己的一个独立实例,这就着不同线程之间的随机数生成器是完全隔离的,而且他们各自内部的种子是完全隔离的,这就保证了随机数生成的独立性,不会因为其他线程的操作而受到影响。

使用方法:

ThreadLocalRandom random = ThreadLocalRandom.current();   // 获取 ThreadLocalRandom 实例

int randomInt = random.nextInt(10, 50); // 生成10到49的随机整数
double randomDouble = random.nextDouble(1.0, 5.0); // 生成1.0到5.0的随机浮点数

虽然 ThreadLocalRandom 解决了 Random 多线程的问题,但是它依然是基于线性同余生成器,导致它生成的随机数序仍然是可预测的。

SecureRandom

由于 java.util.Random 生成的随机数具备可预测性,所以它不适用一些安全要求较高的场景。java.security.SecureRandom 是 Java 提供的一个用于生成加密强度随机数的类,它是 java.security 包的一部分,专门为需要高安全性的应用场景设计,比如加密、安全令牌生成、会话密钥以及数字签名应用。

SecureRandom 生成的随机数具有高安全性,这是因为它使用了更加复杂和不可预测的算法,而且这些算法通常都是基于操作系统提供的随机性源,例如 Unix/Linux 系统的 /dev/random/dev/urandom,或 Windows 的 CryptGenRandom API。所以它更加适用于加密和安全相关的领域。

当然,我们也可以手动设置种子,但是一般不推荐这样做,因为会降低随机数的不可预测性。

SecureRandom 也提供了多种方法来生成不同类型的随机数:

SecureRandom secureRandom = new SecureRandom();

int randomInt = secureRandom.nextInt();
double randomDouble = secureRandom.nextDouble();

我们还可以指定特定的算法来创建 SecureRandom 实例:

SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");

虽然 SecureRandom 生成的随机数具有强大的安全性,但也恰恰如此,导致SecureRandom 在生成随机数时的性能开销比普通的随机数生成器更高。而且在某些情况下,SecureRandom 可能会因为等待足够的熵(随机性)而导致阻塞,尤其是在使用 /dev/random 作为随机性源的系统上。

Java 17 的随机数生成

Java 17 为随机数提供了一个全新的接口 RandomGenerator,该接口是 Java 生成随机数的顶层接口,用于定义所有伪随机数生成器的标准方法。它是所有新的和旧的随机数的顶层接口,包括 java.util.Random

RandomGenerator 提供了两类生成随机数的方法:

  1. 生成随机数:例如 nextInt()nextInt(0, 100)nextLong()

  2. 生成随机数流:例如 ints()longs(),这些方法返回的是一个 Stream,对于生成大量随机数比较有用。

RandomGenerator 实例的创建方法如下:

  1. 使用RandomGenerator.getDefault()

这是获取 RandomGenerator 实例最简单的方式,它返回默认的RandomGenerator实例,适用于大多数用途。

RandomGenerator randomGenerator = RandomGenerator.getDefault();
  1. 使用RandomGenerator.of(String name)

RandomGenerator randomGenerator = RandomGenerator.of("Xoshiro256PlusPlus");  //生成器名称
  1. 使用工厂类RandomGeneratorFactory创建

RandomGeneratorFactory<RandomGenerator> factory = RandomGeneratorFactory.of("Xoshiro256PlusPlus"); //随机数类型
RandomGenerator randomGenerator = factory.create();

得到了 RandomGenerator 实例,就可以调用对应的方法获取对应的随机数了。

RandomGeneratorFactory

RandomGeneratorFactory 是创建 RandomGenerator 实例的工具类,可以用它来创建不同类型的 RandomGenerator 实例,包括但不限于传统的线性同余生成器、梅森旋转算法(Mersenne Twister)、Xoroshiro128++ 算法等。同时它还允许用户根据需求定制随机数生成器的行为,比如设置种子或选择特定的算法。

RandomGeneratorFactory 的核心 API 如下:

  1. of(String name):根据指定的名称创建一个 RandomGenerator 实例。

  2. all():返回所有可用的 RandomGeneratorFactory 实例。

  3. getDefault():返回默认的 RandomGeneratorFactory 实例。

  4. create():使用工厂的配置创建一个新的 RandomGenerator 实例。

下面演示如何使用 RandomGeneratorFactory 创建并使用一个随机数生成器:

@Test
public void randomGeneratorFactoryTest() {
    // 索取所有可用的 随机数类型
    RandomGeneratorFactory.all().forEach(x -> {
        System.out.println(x.name());
    });
    /*L32X64MixRandom
        L64X128MixRandom
        L64X128StarStarRandom
        L64X256MixRandom
        L64X1024MixRandom
        L128X128MixRandom
        L128X256MixRandom
        L128X1024MixRandom
        SecureRandom
        Xoshiro256PlusPlus
        Random
        Xoroshiro128PlusPlus
        SplittableRandom
        */

    // 获取一个类型为 Xoroshiro128PlusPlus 的随机数生成器工厂
    RandomGeneratorFactory<RandomGenerator> factory = RandomGeneratorFactory.of("Xoroshiro128PlusPlus");
    // 使用工厂创建一个随机数生成器
    RandomGenerator randomGenerator = factory.create();
    // 生成 10 个随机数
    randomGenerator.ints().limit(10).forEach(System.out::println);
}

下面是 Java 17 提供 11 个不同的随机数生成器:

类名使用的算法特点
L32X64MixRandomLXM 算法平衡性能和随机性,适用于多种通用应用
L32X64StarStarRandomStarStar算法提供较好的随机性和性能,适用于需要较快随机数生成的场景
L64X128MixRandomLXM 算法提供更长的周期和更高的随机性,适合更复杂的随机数生成需求
L64X128StarStarRandomStarStar算法结合了较长周期和良好的随机性,适用于复杂应用
L64X256MixRandomLXM 算法长周期,高随机性,适合于需求严格的随机数生成场景
L64X1024MixRandomLXM 算法高随机性,适用于特别需要长周期和高随机性的应用
L128X128MixRandomLXM 算法极长周期,高随机性,适合于高随机质量要求的应用
L128X256MixRandomLXM 算法提供极长的周期和优秀的随机性,适用于极高随机质量要求的应用
L128X1024MixRandomLXM 算法极高的随机性和更大的状态空间,适用于对随机数质量有极端要求的场合
Xoshiro256PlusPlusXoshiro算法高性能,适用于需要快速、高质量随机数的应用
Xoroshiro128PlusPlusXoroshiro算法提供良好的性能和随机性平衡,适用于多种应用场景

5、JEP 382:新的 macOS 渲染管道

JEP 338client-libs/2d

使用 Apple Metal API 为 macOS 实现了 Java 2D 渲染管道。新管道减少了 JDK 对已弃用的 Apple OpenGL API 的依赖。

6、JEP 391:macOS/AArch64移植

JEP 391 (hotspot/compiler)

macOS 11.0现在支持AArch64体系结构。这个JEP实现了对JDK中macos-arch64平台的支持。添加的功能之一是支持W^X(写入或执行)内存。它仅针对macos-arch64启用,并可以在某个时候扩展到其他平台。JDK既可以在Intel机器上交叉编译,也可以在基于Apple M1的机器上编译。

7、JEP 398:弃用 Applet API。

JEP 398 (client-libs/java.awt)

Applet 是一种运行在 Web 浏览器内的 Java 程序,早就过时了。

8、JEP 407:删除了远程方法调用 (RMI) 激活机制

JEP 407 (core-libs/java.rmi)

9、JEP 410:删除实验性的 AOT 和 JIT 编译器,

JEP 410hotspot/compiler

这两个实验功能并没有被广泛使用,删除不再维护。

10、JEP 411:弃用安全管理器。

JEP 380 (security-libs/java.security)

11、JEP 403:强封装JDK 内部API

JEP 403

限制外部对 JDK 内部类进行访问,此更改会使应用程序更安全,并减少对非标准、内部 JDK 实现细节的依赖。

12、JEP 412:外部函数和内存 API(孵化特性)

JEP 412 (core-libs)

孵化阶段。

功能进化
java版本特性类型JEP特性
Java 14孵化特性JEP 370引入了外部内存访问 API作为孵化特性
Java 15第二次孵化JEP 383优化外部内存访问 API
Java 16孵化特性JEP 389引入了外部链接器 API
Java 16第三次孵化JEP 393功能优化
Java 17孵化特性JEP 412引入了外部函数和内存 API

引入一个API,它提供对本机代码的静态类型的纯Java访问。此APIForeign-Memory API(JEP 393)一起,将大大简化绑定到本机库的错误处理过程。

13、JEP 414:向量 API(第二次孵化)

JEP 414

这是一个孵化功能。

Vector API 由JEP 338 提出并作为孵化 API 集成到 Java 16 中。

Vector API 旨在通过提供一种在 Java 中编写复杂向量算法的方法来提高向量计算的可预测和健壮性。许多领域都可以从这个显式向量 API 中受益,包括机器学习、线性代数、密码学、金融和 JDK 本身的代码。

功能进化
java版本特性类型JEP特性
Java 16孵化特性JEP 338提供一个平台无关的方式来表达向量计算,能够充分利用现代处理器上的向量硬件指令
Java 17第二次孵化JEP 414改进

14、JEP 415: 上下文特定的反序列化过滤器

JEP 415

15、移除的APIs、工具、容器

参考:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值