Java 13 –深入了解JDK的新功能
由于Java的版本号已经增加了两个,因此您可以快速判断今年的情况! 同时,我们的Java开发人员应该已经习惯了较短的发布周期。 毕竟,我们现在可以定期尝试新功能,而且每隔几年就不会因各种新功能而被淘汰。 在本文中,我们将了解Java 13,该Java今天于2019年9月17日发布。
Java 13一目了然
- JEP 350:动态CDS存档
- JEP 351:ZGC:取消提交未使用的内存
- JEP 353:重新实现旧版套接字API
- JEP 354:开关表达式(预览)
- JEP 355:文本块(预览)
乍一看,看起来并不多。 实际上,由于自Java 12发行以来的时间很短,我们真的不能期望太多的更改。 取而代之的是,长期支持(LTS)版本之间的发行版大多在其中提供某些功能作为预览,以便获得用户的早期反馈。 这些功能在JEP中实现,并且一旦达到一定的成熟度,就会在规定的半年周期的下一个版本中交付。
这使得无法准确预测下一个发行版中将包含多少与典型Java程序员相关的新功能。 目标是在下一个LTS版本中最终确定预览功能,以使它们足够稳定并在未来三年中保持良好状态。 在2021年9月,Java 17将取代Java 8和11。
开关表达式的增强
如果从开发人员的角度来看上面的功能列表,那么最后两点主要是有趣的。 例如,由于用户反馈,已扩展了Java 12中作为预览引入的开关表达式。 Switch表达式是繁琐且容易出错的Switch语句的替代方法。 有关其用法的详细概述,请参见Java 12的各种文章 。
Java 13中最大的变化是用yield替换了switch表达式中的关键字break。 背景是switch语句(可能有中断)和表达式(有yield)之间的更好区分。 yield语句退出开关并返回当前分支的结果,类似于return。
清单1中显示了一个代码示例。在上面,我们看到一条带有break and fall through的语句。 在直接比较中,带有新关键字yield和多个标签的switch表达式。 与第一个变体相比,变量没有更改,但是case分支的结果直接返回。
// Switch-Statement with break
private static String statementBreak(int switchArg){
String str = "not set";
switch (switchArg){
case 1:
case 2:
str = "one or two";
break;
case 3:
str = "three";
break;
};
return str;
}
// Switch-Expression with yield
private static String expressionBreakWithValue(int switchArg){
return switch (switchArg){
case 1, 2: yield "one or two";
case 3: yield "three";
default: yield "smaller than one or bigger than three";
};
}
Java 12中引入的Arrow语法仍然有效(清单2)。
private static String expressionWithArrow(int i) {
return switch (i) {
case 1, 2 -> "one or two";
case 3 -> "three";
default -> "smaller than one or more than three";
};
}
开关表达式暂时仍处于预览状态,因此将来的Java版本中可能会有进一步的调整。 因此,在使用JDK 13进行编译时,必须指定相应的标志:
javac --release 13 --enable-preview Examples.java
预览功能还必须在启动时**。 当然,构建工具(Maven等)也具有配置开关:
java --enable-preview Examples
文本块而不是原始字符串文字
实际上,文本块只是原始计划用于Java 12的Raw String Literals(JEP 326)的一小部分。Raw String Literals的第一个实现尚未考虑到最后一个细节,用户的反馈提出了许多问题。 详细信息可以在邮件列表中找到。 Java 13“仅”目前具有多行文本块。
但这总比没有好。 毕竟,许多Java应用程序都处理来自其他语言(例如HTML或SQL)的代码段,为清楚起见,它们通常由几行组成。 到目前为止,只能以非常麻烦的方式定义此类字符串,这使它们难以阅读。 例如,必须使用额外的控制命令(使用\ n转义)来换行。 诸如Groovy,Scala或Kotlin之类的其他语言早就提供了定义多行文本的可能性。
新的文本块使用三引号作为分隔符,并且可以在允许使用常规字符串的任何地方使用。 清单3显示了传统语法和新语法之间的区别。 首尾三引号必须放在单独的行中。 但是,实际内容从第二行开始。 因为第一行的缩进在源文本中正确显示,所以这增加了源代码的可读性。
// Without Text Blocks
String html = "<html>\n" +
" <body>\n" +
" <p>Hello, Escapes</p>\n" +
" </body>\n" +
"</html>\n";
// With Text Blocks
String html = """
<html>
<body>
<p>Hello, Text Blocks</p>
</body>
</html>""";
可以在TimZöller的文章中找到更多示例,该文章专门针对JEP 355 。 文本块在编译时由普通字符串替换; 在字节码中,您将不再看到最初定义字符串的方式。
动态CDS档案
除了对开发人员显而易见的新功能外,在JVM的内部和类库中还发生了很多事情。 Java 5中引入了类数据共享(CDS)。CDS的目标是通过将有关类的某些信息存储在类数据共享档案中,从而缩短Java应用程序的启动时间。 然后可以在运行时加载此数据,并由多个JVM使用。
但是,在Java 10之前,共享存档只能由Bootstrap类加载器访问。 从Java 10开始,CDS通过应用程序类数据共享(AppCDS)进行了扩展。 AppCDS使内置系统和平台类加载器以及用户定义的类加载器能够访问CDS档案。 创建CDS归档文件需要类列表,以标识要加载的类。
还请参见:
以前,这些类列表必须通过应用程序的试运行来确定,以确定在执行期间实际加载了哪些类。 从Java 12开始,默认情况下,默认的CDS归档文件随JDK一起提供,它们基于JDK的类列表。
现在,动态CDS存档基于此。 目的是保存应用程序的其他测试运行。 执行应用程序后,仅归档默认/基本层CDS中尚未包含的新装入的应用程序和库类。 动态归档是通过命令行命令**的。 在将来的扩展中,类的归档将可以完全自动且透明地运行。
ZGC返回未使用的存储
如今,应用程序必须同时为成千上万的用户提供服务已经很普遍。 这些应用程序需要大量内存,内存管理并非易事,并且会影响应用程序的性能。 为了满足这些要求,Oracle在Java 11中引入了Z垃圾收集器(ZGC)。在清理具有数TB的堆内存时,它保证了非常短的暂停。
但是,以前它没有释放为应用程序保留的堆内存。 结果,应用程序在其整个生命周期内通常消耗的内存远远超过所需的内存。 在资源不足的环境中运行的应用程序尤其受到影响。 G1和Shenandoah等其他垃圾收集器已经支持释放未使用的内存。
更新的套接字API
java.net.Socket和java.net.ServerSocket API及其底层实现是JDK 1.0的残余。 它们中的大多数由旧版Java和C代码组成。 这使得维护和扩展性变得更加困难。 NioSocketImpl应该现在替换过时的PlainSocketImpl。 NioSocketImpl基于现有的New I / O实现,并在JDK中使用其现有的基础结构。
先前的实现也与该语言的其他计划的扩展不兼容。 例如,并发问题阻碍了轻量级用户线程(光纤,Project Loom的一部分)的未来使用。
结论
到目前为止描述的更改是在JEP(Java增强建议)中定义的。 但是,直接在类库中进行进一步的修改。 这些可以使用JDK API Diff Report Generator或Java Almanac可视化。 仔细研究发现,旧的Doclet API已从com.sun.javadoc中删除 。 此外,作为JEP 355(文本块)的一部分,在String类中添加了三个新的实例方法:formatted,stripIndent和translateEscapes。
从Java 10开始,我们可以期待每年两次(三月和九月)发布新的Java。 当然,由于半年之内开发工作不会太多,因此幸运的是可以管理各个功能列表。 但是,较短的更新周期使我们能够在较短的间隔内定期试用新功能。 Oracle的Java团队可以就这些新功能获得更快,更有价值的反馈,其中一些功能处于一个或多个版本的预览状态。 在进入下一个LTS版本的过程中,将有用户反馈并根据需要进行更改。 例如,在当前的LTS版本Java 11中,从Java 9和10开始的工作已经完成。
为了有效使用其Java应用程序,可以同时在两个变体之间进行选择。 您可以使用当前的LTS版本三年,也可以每年两次更新到OpenJDK的主要版本,而Oracle则将其更新了半年。 后者可以免费使用,但必须在六个月后更新到下一个版本,以便继续接收安全更新和补丁。 使用LTS版本时,既有付费优惠(Oracle,Azul等),也有免费安装,如AdoptOpenJDK,Amazon Corretto,RedHat,SAP和阿里巴巴Dragonwell。 在Oracle的新许可政策让人们大吃一惊之后,现在有许多替代方案可以在生产环境中运行Java。
另外,Oracle的想法似乎可以与半年一次的主要版本和定期的(尽管很小的)更新一起使用。 到目前为止,版本已按宣布的准时交付,因此我们已经可以期待下一次更改。 但是首先我们必须安装JDK 13并尝试新功能。 Java版本14的工作已经并行运行。 在撰写本文时,已经计划了JEP 352(非易失性映射字节缓冲区)。 另外,可以最终确定开关表达式和文本块的预览。 此外,JEP 343的框架中可能会出现一种用于打包自包含Java应用程序的新工具。但是,尽管这些更改目前尚不确定,但下一个版本已经面世。 因为在2020年3月,我们将再次说“每半年”…
翻译自: https://jaxenter.com/java-13-jdk-deep-dive-new-features-162272.html