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类Random、ThreadLocalRandom和SplittableRandom,在应用程序中很难用其他算法取代它们中的任何一个,因为它们没有任何超类型来支持运行时的变化。
随着RandomGenerator 接口的引入,我们可以在应用程序代码中注入任何客户端使用RandomGenerator 类型的实现发生器类。这些新的类是
- SplittableGenerator- 可以被分割成两个对象(原始对象和新对象),每个对象都遵守该协议。
- JumpableGenerator--可以很容易地向前跳,幅度适中。
- 可跳跃的生成器--不仅可以很容易地跳跃,而且可以很容易地向前跳跃,跳跃的幅度很大。
- ArbitrarilyJumpableGenerator--可以很容易地向前跳跃,以一个任意的数量,跳到状态周期中的一个遥远的点。
- StreamableGenerator--增强了RandomGenerator接口,以提供返回RandomGenerator对象流的方法。
此外,传统的随机类,如Java.util.Random、SplittableRandom、ThreadLocalRandom和SecureRandom现在也扩展了新的RandomGenerator接口。
2.4.2.随机生成器工厂(RandomGeneratorFactory
RandomGeneratorFactory提供了选择随机数生成器算法的方法。我们可以通过它的名字选择一个特定的算法,并使用它来生成随机数。
默认算法是L32X64MixRandom。下面是所有支持的算法的列表。
- L128X1024MixRandom
- L128X128MixRandom
- L128X256MixRandom
- L32X64MixRandom
- L64X1024MixRandom
- L64X128MixRandom
- L64X128StarStarRandom
- L64X256MixRandom
- 随机(遗留)
- 安全随机(遗留)
- 可拆分的随机(遗留)
- Xoroshiro128PlusPlus
- Xoshiro256Plus
Legecy 组代表旧的PRNGs。请注意,这些新的实现都不是线程安全的,而Java.util.Random和Java.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迁移做好计划。
学习愉快!!