简介2021年9月,JDK17发布。JDK17是最新的LTS版本。所谓LTS版本,就是至少可以获得八年产品支持的版本。从2014年的JDK8,到2018年的JDK11,再到2021年的JDK17。同时,甲骨文还调整了LTS版本的发布周期,从之前的三年调整到现在的两年,这意味着下一个LTS版本将是JDK21,哇!那么如果它不是LTS版本呢?非LTS版本只会获得六个月的产品支持。所以大家还是用LTS版本。好吧,让我们来看看JDK17中的新特性。JDK17中的新特性总的来说,JDK17提供了14个优化点或改变点。我们将一一解释。新语言特性JDK17只有一个新语言特性JEP409:SealedClasses。SealedClasses是JDK15引入的概念,表示一个类允许继承哪些类:publicsealedclassSealExamplepermitsSeal1,Seal2{}publicnon-sealedclassSeal1extendsSealExample{}publicfinalclassSeal2extendsSealExample{}finalmeansSeal2不能再被继承。非密封意味着任何类都可以被继承。核心库优化JDK17对JAVA核心库有4处优化。第一个是:JEP306:恢复始终严格的浮点语义这是什么?简单来说,以前的硬件架构在执行严格的浮点语义计算时,会消耗大量资源。这在很久以前硬件水平不高的时候是不能接受的。所以在JDK1.2之后,对浮点语义进行了微调,修改了默认的严格浮点语义。但是现在已经2021年了,硬件层面发展很快,所以之前介绍的修改已经没有必要了,在JDK17中已经舍弃了。二是:JEP356:EnhancedPseudo-RandomNumberGeneratorJDK有一个类java.util.Random专门生成随机数,但是这个类生成的是伪随机数。JDK17对这个类进行了增强,提供了RandomGenerator接口,为所有的伪随机数提供统一的API。RandomGenerators提供了ints、longs、doubles、nextBoolean、nextInt、nextLong、nextDouble、nextFloat等方法生成对应的随机数。RandomGenerator接口包括4个子接口,分别是:SplittableRandomGenerator:提供split和splits方法,允许用户从现有的RandomGenerator生成新的RandomGenerator。JumpableRandomGenerator:扩展了RandomGenerator的jump和jumps方法,允许用户跳过一定数量的随机数。LeapableRandomGenerator:扩展了RandomGenerator的leap和leaps方法,允许用户跳过大量的随机数。ArbitrouslyJumpableRandomGenerator:扩展LeapableRandomGenerator,允许用户指定要跳过的随机数。Random、ThreadLocalRandom和SplittableRandom类也进行了重构。第三个是JEP382:NewmacOSRenderingPipeline,专门为Mac优化,使用最新的AppleMetalAPI在JAVA中实现2D渲染。第四个是JEP415:Context-SpecificDeserializationFiltersJDK中一个非常危险的用法是反序列化,因为你不知道反序列化的对象是否是危险对象。为了解决这个问题,Java9引入了一个反序列化过滤器,在反序列化前对数据流进行校验。但是这种基于流的过滤器有几个局限性,这种方法不能扩展,代码发布后很难更新过滤器。它也无法过滤应用程序中第三方库执行的反序列化操作。为了解决这些问题,JEP290还引入了JVM范围的反序列化过滤器,可以通过API、系统属性或安全属性进行设置。但是这种静态过滤器往往不适用于具有多个执行上下文的复杂应用,因为不同的上下文可能需要不同的过滤条件。JDK17改进了JDK9的过滤方式,可以在JVM范围配置context-specific反序列化过滤器。支持新平台JEP391:macOSAArch64PortMac的M1芯片已经发布很久了,JDK没有理由不支持,这个JEP就是让JDK17支持原生苹果新的Arm64架构。预览特性JEP406:开关模式匹配(预览)这个新特性允许在开关中使用模式匹配。我们知道,在前面的预览函数中,已经有了模式匹配,只是模式匹配用在了instanceofstatement中,如下所示://Oldcodeif(oinstanceofString){Strings=(String)o;...uses...}//newcodeif(oinstanceofStrings){...uses...}但是如果instanceof太多的话会出问题:staticStringformatter(Objecto){String格式化=“未知”;if(oinstanceofIntegeri){formatted=String.format("int%d",i);}elseif(oinstanceofLongl){formatted=String.format("long%d",l);}elseif(oinstanceofDoubled){formatted=String.format("double%f",d);}elseif(oinstanceofStrings){formatted=String.format("String%s",s);}returnformatted;}最好的方法是将上面的代码转换成一个switch:staticStringformatterPatternSwitch(Objecto){returnswitch(o){caseIntegeri->String.format("int%d",i);caseLongl->String.format("long%d",l);caseDoubled->String.format("double%f",d);case字符串s->String.format("字符串%s",s);默认->o.toString();};}这是switch中的模式匹配JEP412:ForeignFunctionandMemoryAPI(Incubator)在JDK14和15中,JDK已经可以调用不属于JVM的代码,访问不属于JVM管辖的内存空间虚拟机。这个新特性在JDK17中得到了增强。想象一下,未来JDK可以原生支持调用非java语言的API,是不是很神奇?JEP414:VectorAPI(SecondIncubator)Vector是在JDK16中引入的。可以使矢量计算更快。用Vector可以简化循环遍历的计算。其他变化其他一些变化,如封装JDK内部使用的API,放弃SecurityManager、AppletAPI和RMI等,这里不再介绍。综上所述,JDK17是一个LTS版本,同时也提供了很多优秀的新特性,赶快用起来吧!本文已收录于http://www.flydean.com/27-jdk17-new-features/最流行的解读,最深刻的干货,最简洁的教程,很多你不知道的小技巧等着你等你发现!欢迎关注我的公众号:《程序那些事儿》,懂技术,更懂你!
