欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java 13 –深入了解JDK的新功能

程序员文章站 2022-04-19 22:00:10
...

由于Java的版本号已经增加了两个,因此您可以快速判断今年的情况! 同时,我们的Java开发人员应该已经习惯了较短的发布周期。 毕竟,我们现在可以定期尝试新功能,而且每隔几年就不会因各种新功能而被淘汰。 在本文中,我们将了解Java 13,该Java今天于2019年9月17日发布。

Java 13一目了然

以下Java增强建议已纳入JDK 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 GeneratorJava 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