Java 17的特点和增强功能

1,552 阅读6分钟

Java 17于2021年9月14日发布。Java 17是一个LTS(长期支持)版本,像Java 11和Java 8一样。甲骨文公司将在未来几年内支持它的错误修复、补丁和性能提升。

Spring 6和Spring boot 3将对Java 17有一流的支持。因此,计划升级到Java 17是一个好主意。

我们可以从这个链接*下载Java 17*。

2.开发人员的Java 17功能

让我们谈谈哪些JEP会直接影响到开发人员的日常工作。

2.1.恢复始终严格的浮点语义

这个JEP针对的是涉及浮点数字的科学计算。为了保证在所有平台上都有相同的计算结果,我们一直在使用关键字strictfp

*strictfp*修改器通过将所有中间值表示为IEEE单精度和双精度值来实现这一目的。但由于硬件加热问题,它在JDK 1.2中变成了可选的。

今天,随着硬件的发展和这些发热问题的解决,默认的浮点语义已经改为一致的严格

有了这个变化,我们就不需要再使用strictfp 关键字了。

2.2.开关的模式匹配 (预览)

这一变化增加了对开关语句和表达式的模式匹配。由于这是一个预览功能,我们需要使用**-enable-preview**选项来启用它。

2.2.1.不需要明确的null 检查

传统的switch 语句,如果选择器表达式求值为null ,则抛出NullPointerException 。有了这个改变,我们可以把这种表达式作为单独的案例本身来检查。

if (s == null) {
    System.out.println("oops!");
    return;
}
switch (s) {
    case "Foo", "Bar" -> System.out.println("Great");
    default           -> System.out.println("Ok");
}
switch (s) {
    case null         -> System.out.println("Oops");
    case "Foo", "Bar" -> System.out.println("Great");
    default           -> System.out.println("Ok");
}

2.2.2.改进的instanceof 检查

在Java 16之前,如果我们必须写一段代码来检查实例类型并执行一些逻辑,这就是方法。

Object o;
if (o instanceof String) 
{
    String s = (String) o;
    String.format("String %s", s)
} 
else if (o instanceof Integer) 
{
    Integer i = (Integer) o; 
    String.format("int %d", i)
} 
else if (o instanceof Double) 
{
    Double d = (Double) o;
    String.format("double %f", d)
}

在Java 16中,我们可以用更简单的方式来写上述表达式。

Object o;
if (o instanceof String s) 
{
    String.format("String %s", s)
} 
else if (o instanceof Integer i) 
{
    String.format("int %d", i)
} 
else if (o instanceof Double d) 
{
    String.format("double %f", d)
}

Java 17通过switch表达式把它提高到了一个新的水平。现在我们可以将上述代码改写为。

Object o;
switch (o) 
{
    case Integer i -> String.format("int %d", i);
    case Double d  -> String.format("double %f", d);
    case String s  -> String.format("String %s", s);
    default        -> o.toString();
}

虽然做了上述改变,但已确保所有旧的开关表达式必须继续工作。你可以在JEP网页上看到所有对switch 表达式的改变。

2.3.密封的类

在Java中,默认情况下,对一个类可以实现哪些公共接口没有任何限制。从Java 15开始,我们可以使用修饰符sealed来声明一个密封的类或接口

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

public sealed class Account
    permits CurrentAccount, SavingAccount, LoanAccount {
}

这在Java 15和Java 16中是一个预览功能。在Java 17中,它已经成为一个标准功能,与Java 16中的功能没有任何变化。

阅读更多:密封类和接口

2.4.增强的伪随机数生成器

2.4.1.随机生成器

本JEP引入了一个名为RandomGenerator 的新接口,旨在使未来的伪随机数发生器(PRNG)算法更容易实现或使用。

对于传统的PRNG类RandomThreadLocalRandomSplittableRandom,在应用程序中很难用其他算法取代它们中的任何一个,因为它们没有任何超类型来支持运行时的变化。

随着RandomGenerator 接口的引入,我们可以在应用程序代码中注入任何客户端使用RandomGenerator 类型的实现发生器类。这些新的类是

  • SplittableGenerator- 可以被分割成两个对象(原始对象和新对象),每个对象都遵守该协议。
  • JumpableGenerator--可以很容易地向前跳,幅度适中。
  • 可跳跃的生成器--不仅可以很容易地跳跃,而且可以很容易地向前跳跃,跳跃的幅度很大。
  • ArbitrarilyJumpableGenerator--可以很容易地向前跳跃,以一个任意的数量,跳到状态周期中的一个遥远的点。
  • StreamableGenerator--增强了RandomGenerator接口,以提供返回RandomGenerator对象流的方法。

此外,传统的随机类,如Java.util.RandomSplittableRandomThreadLocalRandomSecureRandom现在也扩展了新的RandomGenerator接口。

2.4.2.随机生成器工厂(RandomGeneratorFactory

RandomGeneratorFactory提供了选择随机数生成器算法的方法。我们可以通过它的名字选择一个特定的算法,并使用它来生成随机数。

默认算法是L32X64MixRandom。下面是所有支持的算法的列表。

  • L128X1024MixRandom
  • L128X128MixRandom
  • L128X256MixRandom
  • L32X64MixRandom
  • L64X1024MixRandom
  • L64X128MixRandom
  • L64X128StarStarRandom
  • L64X256MixRandom
  • 随机(遗留)
  • 安全随机(遗留)
  • 可拆分的随机(遗留)
  • Xoroshiro128PlusPlus
  • Xoshiro256Plus

Legecy 组代表旧的PRNGs。请注意,这些新的实现都不是线程安全的,而Java.util.RandomJava.security.SecureRandom都是。

RandomGeneratorFactory factory = RandomGeneratorFactory.of("SecureRandom")
RandomGenerator random = factory.create(200L);

//get random numbers
randomGenerator.nextDouble();

2.5.废弃Applet API的删除

出于安全考虑,大多数网络浏览器已经取消了对Applet的支持。在Java 9中,Applet API被标记为弃用。

由于它在今天已经变得无关紧要,Java 17已经将其标记为删除。

2.6.强化封装JDK内部结构

这个 JEP 强烈地封装了 JDK 的所有内部元素,但关键的内部 API(如sun.misc.Unsafe)除外。

从Java 9到Java 16,开发人员能够使用标志–illegal-access 来访问JDK的内部API。Java 17将忽略该标志,如果该标志存在。

控制台将显示一条消息,告知该标志的停用。

2.7.移除RMI激活

移除远程方法调用(RMI)激活机制,同时保留RMI的其余部分。它已经过时了,在Java 15中被废弃。

2.8.移除实验性AOT和JIT编译器

该JEP删除了Java 9和Java 10中引入的基于Java的实验性超前(AOT)和及时(JIT)编译器。

Graal编译器是通过JEP 317在JDK 10中作为实验性JIT编译器提供的。自从它们被引入后,很少有人使用这些实验性的功能,而且维护和增强这些功能所需的努力也很重要。

开发者仍然可以使用GraalVM来利用这些功能。

3.总结

Java 17有很多令人兴奋的功能,也有很长的支持和承诺之路。它从Java中删除了许多已经废弃的API。

发现任何仍在使用这些废弃功能的应用程序的机会明显减少,但是,在迁移到Java 17之前,开发人员必须谨慎地彻底检查应用程序的代码和依赖关系。

由于Java 17是一个LTS版本,而主要的流行框架(如Spring 6和Spring Boot 3)将支持新的功能,因此最好为Java 17迁移做好计划。

学习愉快!!