JavaRush /Java 博客 /Random-ZH /Java 14:有什么新变化?

Java 14:有什么新变化?

已在 Random-ZH 群组中发布
世界的问题就是世界的问题,新的Java如期而至。也就是说,每六个月一次。Java 14 的发布版本于 3 月 17 日发布,针对开发人员为该语言引入了几项有趣的创新。 其中包括对recordJava 14:有什么新变化? - 1关键字的实验性支持、对“ instanceof ”运算符中的模式匹配的支持、更用户友好的NullPointerExceptions 、扩展的文本块“预览” 、更新的默认开关等等。让我们提醒您,Java 中的所有创新都始于扩展提案(JEP,Java 增强提案)。开发人员提出更改,由“官方”Java 父辈进行审查,然后其中一些更改被接受,之后它们就成为 JDK 的一部分。现在——一切都井然有序。

JEP 359:记录

Records,也称为 Records,在 JDK 14 中以预览模式提供,这对于 Java 来说是全新的东西。事实上,我们面前有一种在瓦尔哈拉项目期间开发的新型。记录与枚举类似,可以让您简化代码。本质上,它们取代了具有状态但没有行为的类。简单来说,有字段,没有方法。就类而言,我们有时不得不编写大量并不总是必要的重复代码:构造函数、访问器、equals()、hashCode()、toString()等。为了避免这种重复代码,Java 计划使用记录。这是经典版本:
final class Triangle {
 	public final int x;
public final int y;
public final int z;

    public Triangle(int x, int y, int z) {
         this.x = x;
         this.y = y;
    this.z = z;
    }
    // equals, hashCode, toString
让我们转向 Java 14 并使用记录:
public record Triangle(int x, int y, int z){}
就这样。请注意,录音目前以预览形式存在,因此要在实践中尝试它们,您需要下载 jdk14 并输入命令:
javac —enable-preview —release 14 Triangle.java
记录是类,尽管有局限性。它们不能扩展其他类或声明字段(除了对应于状态声明组件的私有final)。记录是隐式最终的并且不能是抽象的。记录与常规类的不同之处在于它们无法将其 API 与其表示形式分开。但准确性的提高弥补了自由度的损失。记录组件也是隐式最终的。

JEP 305:instanceof 的模式匹配(预览版)

Java 14 预览版中引入的模式匹配功能旨在将对象类型检查及其在instanceof运算符中的转换结合起来。换句话说,在 Java 14 之前,会有如下代码:
Object object = Violin;

if (object instanceof Instrument) {
    Instrument instrument = (Instrument) object;
    System.out.println(instrument.getMaster());
}
正如您所看到的,我们必须将对象强制转换为我们要使用其方法的类。现在,Java 14 和连接的模式匹配功能允许您将代码缩减为以下内容:
Object object = Violin;

if (object instanceof Instrument instrument){
    System.out.println(instrument.getMaster());
}

JEP 343:打包工具(孵化器)

JDK 8 有一个专为 JavaFX 设计的javapackager工具。然而,随着 JDK 11 的发布,JavaFX 与 Java 分离,流行的 javapackager 不再可用。 Javapackager是一个打包工具。它允许 Java 应用程序以这样的方式打包,以便可以像所有其他“正常”程序一样安装它们。例如,为 Windows 用户创建 exe 文件,然后像人类一样双击启动 Java 应用程序。当然,这样的工具非常缺乏,因此JEP 343引入了一个新工具jpackage,它将 Java 应用程序打包到包含所有必要依赖项的特定于平台的包中。特定平台支持的包格式:
  • Linux:deb 和 rpm
  • macOS:pkg 和 dmg
  • Windows:MSI 和 EXE

JEP 345:G1 的 NUMA 感知内存分配

JEP 345 仅用于实现 NUMA(非均匀内存访问)支持。这些是异构内存访问架构,是一种将微处理器集群设置为多处理器系统的方法,其中内存可以本地分布:每个处理器核心获得少量本地内存,而其他核心可以访问它。JEP 345 计划为 G1 垃圾收集器配备利用此类架构的能力。除此之外,这种方法有助于提高功能强大的机器的性能。

JEP 349:JFR 事件流

Java Flight Recorder (JFR)现在是 OpenJDK 的一部分,因此可以免费使用。JDK 14 添加了一个用于动态跟踪 JFR 事件的 API(JDK Flight Recorder),特别是用于组织对活动和非活动应用程序的持续监控。记录的事件与非流选项相同,开销不到 1%。这样,事件将与非流式传输选项同时进行流式传输。但是,JEP 349 不得允许相应使用者的同步回调。即使是存储在中间存储器中的记录中的数据也不应该是可访问的。从技术上讲,jdk.jfr 模块中的 jdk.jfr.consumer 包将扩展异步访问事件的功能。

JEP 352:非易失性映射字节缓冲区

众所周知,Java NIO(新IO)文件API从JDK 1.4开始就已经存在,然后引入了一个名为Path的新增强功能。Path 是一个接口,当我们在 Java NIO 中工作时,它会取代 java.io.File 类来表示文件或目录。JEP 352 扩展了 MappedByteBuffer 以将一部分文件数据加载到非易失性存储器 (NVM) 中。这种即使断电数据也不会丢失的计算机存储器(通常称为只读存储器)用于永久存储数据。这个Java增强提案为JDK API提供了一个新的模块和类:jdk.nio.mapmode模块,它提供了新的模式(READ_ONLY_SYNC、WRITE_ONLY_SYNC)来创建引用NVM的映射字节缓冲区(MappedByteBuffer)。

JEP 358:有用的 NullPointerExceptions

NullPointerExceptions现在对程序员更加友好。从某种意义上说,异常的描述将比以前提供更多信息。这是因为 JVM 被教导能够更准确地分析程序字节码指令,并且它可以指示哪个变量导致零值。假设我们有代码:
a.getMessage().getUserInfo().getName()
在任何最新的Java中,我们都会得到通常的错误日志,它并没有回答到底谁是null的问题:
Exception in thread "main" java.lang.NullPointerException
	at Main.main(Main.java:12)
如果您决定尝试此预览功能,Java 14 将为您提供以下功能:
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "UserInfo().getName()" because the return value of "Message().getUserInfo()" is null
	at Main.main(Main.java:12)
该链更容易理解,并且可以让您更快地解决错误。

JEP 361:开关表达式(标准)

更新后的 Switch 运算符已在之前的 Java 12 和 13 中提供,但仅作为预览功能,即默认情况下不启用。现在,在 JDK 14 中,一切都可以开箱即用。Java 14 引入了带有 case L -> ... 标签的 switch 块的新简化形式。新形式在某些情况下简化了代码。这里有几个例子。假设我们有一个描述一周中的日子的枚举。我们可以编写经典代码(Java 14 之前的版本):
switch (day) {
    case MONDAY:
    case FRIDAY:
    case SUNDAY:
        System.out.println(6);
        break;
    case TUESDAY:
        System.out.println(7);
        break;
    case THURSDAY:
    case SATURDAY:
        System.out.println(8);
        break;
    case WEDNESDAY:
        System.out.println(9);
        break;
}
这是使用 Java 14 的一个选项:
switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);
    case TUESDAY                -> System.out.println(7);
    case THURSDAY, SATURDAY     -> System.out.println(8);
    case WEDNESDAY              -> System.out.println(9);
}
您还可以编写多行块并使用新的yield关键字返回一个值:
int result = switch (s) {
    case "Working from Home" -> 1;
    case "Working from Office" -> 2;
    default    -> {
        System.out.println("Neither Home nor Office… Cafe? Car? Park?...");
        yield 0;
    }
};
使用新开关 时,还有一些更重要的事情需要记住。特别是,您需要记住选项必须是详尽的。也就是说,对于所有可能的值都必须有一个对应的开关标签。由于yield现在是一个关键字,因此Java 14中可以有一个名为yield的类。一般来说,如果您想学习如何使用更新的开关,请转到JEP 361并学习。那里有很多有趣的信息。

JEP 362:弃用 Solaris 和 SPARC 端口

我们的许多读者不太可能记得Solaris操作系统。这个基于 UNIX 的操作系统,由 Java 的父母 Sun Microsystems 创建,主要用于 SPARC 架构上的服务器...... 每平方厘米有太多陌生的单词?没什么大不了的:JEP 362 终止了对 Solaris/SPARC、Solaris/x64 和 Linux/SPARC 平台的支持。也就是说,它们的端口现已弃用,将来它们很可能会从 OpenJDK 中删除。但是,有关 Solaris/SPARC、Solaris/x64 和 Linux/SPARC 端口的旧版 Java(JDK 14 之前的版本)无需修改即可运行。如果您是历史爱好者并且对不远的过去的技术感兴趣,请访问维基百科并阅读有关SPARС架构的信息。

JEP 363:删除并发标记扫描 (CMS) 垃圾收集器

CMS 垃圾收集器(并发标记清除)是被删除的目标,因为它在两年前被标记为过时且无人维护。然而,使用 CMS GC 的旧版 Java 用户可能会松口气——这个 JEP 的目的并不是从早期 JDK 版本中删除构建器。此外,ParallelScavenge 和 SerialOld 垃圾收集算法的组合(使用“-XX:+UseParallelGC -XX:-UseParallelOldGC”选项运行)已被弃用。

JEP 364:macOS 上的 ZGCJEP 365:Windows 上的 ZGC

有一个有趣的垃圾收集器,称为Z 垃圾收集器 (ZGC)。它工作在被动模式下,并尽量减少垃圾收集造成的延迟:使用 ZGC 时的停止时间不超过 10 ms。它可以处理小堆和巨型堆(占用许多 TB 的堆)。JEP 364 和 JEP 365 实际上是双胞胎。JEP 364 将 Z 垃圾收集器引入 MacOS。JEP 的一部分还描述了用于释放未使用的设备内存的收集器功能,如JEP 351中所指定,自 Java 13 以来一直在发生这种情况。macOS 上的 ZGC 实现分为两部分:
  • macOS 上的多重映射内存支持
  • ZGC 支持连续内存预留
JEP 365 已经在 Windows 上提供了对 ZGC 的支持,并且还处于实验模式。如下:
  • 多映射内存支持
  • 支持基于页面文件的内存映射到保留的地址空间
  • 支持映射和取消映射堆的任意部分
  • 支持提交和取消提交堆的任意部分

JEP 366:弃用 ParallelScavenge + SerialOld GC 组合

此 JEP 不赞成并行 Scavenge 和串行旧垃圾收集算法的组合。必须使用命令行参数 -XX: + UseParallelGC -XX: -UseParallelOldGC 手动启用此组合。作者认为这种组合非常具体,但也需要大量的维护工作。因此,现在 -XX: UseParallelOldGC 选项已被弃用,如果使用,将会出现警告。

JEP 367:删除 Pack200 工具和 API

Pack200是一种针对存储已编译的 Java 类文件而优化的存档格式。该工具自 Java 11 起已被标记为已弃用。现在 pack200、unpack200 和 Pack200 API 工具已正式宣布从 java.util.jar中删除。这项技术早在 Java 5 中就被引入,作为一种处理非常有限的带宽(调制解调器,说起来可怕,记住,56k)和硬盘驱动器上存储空间不足的方法。不久前,Java 9 引入了新的压缩方案。鼓励开发人员使用jlink

JEP 368:文本块(第二次预览)

文本块首次出现在 Java 13 中。它们是多行字符串文字,不需要大多数转义序列,自动格式化字符串,并且还允许开发人员在必要时格式化字符串。这个有用的功能现在在 Java 14(第二个预览版)中可用。文本块的主要目的是改进对令人困惑的多行文字的处理。这极大地简化了 SQL 查询、HTML 和 XML 代码以及 JSON 的读写。没有文本块的 HTML 示例:
String html = "<html>\n" +
              "    <body>\n" +
              "        <p>Hello, JavaRush Student</p>\n" +
              "    </body>\n" +
              "</html>\n";
如何用文本块表示相同的内容:
String html = """
              <html>
                  <body>
                      <p>Hello, JavaRush Student</p>
                  </body>
              </html>
              """;
开始分隔符是三个双引号字符 ("" ") 的序列,后跟零个或多个空格,然后是行分隔符。内容从开始分隔符的行分隔符之后的第一个字符开始。结束分隔 是选择三个双引号字符 ,以便可以在不转义的情况下显示字符,并且还可以在视觉上区分文本块和字符串文字。2019 年初,JEP 355 提议将文本块作为 JEP 326(原始字符串文字)的延续,但已被撤回。同年晚些时候,JDK 13 引入了文本块预览功能,现在 Java 14 添加了两个新的转义序列。这是一个行终止符,表示为 \,第二个是单个空格,表示为 /s。使用不带文本块的换行符的示例:
String literal = "This is major Tom to Ground Control " +
"I am stepping through the door... " +
"Wait… What???";
现在使用转义序列 \<line-terminator>:
String text = """
                This is major Tom to Ground Control \
                I am stepping through the door... \
                WaitWhat???\
                """;
转义序列\s用于解释尾随空白,默认情况下编译器会忽略该空白。它保留其前面的所有空白。例子:
String text1 = """
               line1
               line2 \s
               line3
               """;

String text2 = "line1\nline2 \nline3\n";
text1并且text2是相同的。

JEP 370:外部内存访问 API(孵化器)

许多流行的 Java 库和程序都可以访问外部存储器。例如,Ignite、MapDB、Memcached 和 Netty ByteBuf API。这样做,他们可以避免与垃圾收集相关的成本和不可预测性(特别是在服务大型缓存时),跨多个进程共享内存,并通过在内存中映射文件(例如,使用 mmap)来序列化和反序列化内存内容。然而,Java API仍然没有合适的访问外部内存的解决方案。JDK 14 包含外部内存访问 API的预览版,该 API 允许 Java 应用程序使用新的 MemorySegment、MemoryAddress 和 MemoryLayout 抽象安全高效地访问 JVM 堆外部的内存区域。

结论

所以你怎么看?与 Java 13 相比,新的 Java 14 在各个领域提供了许多更重要的改进。对于开发人员来说最重要的很可能是更新的开关、扩展异常 NullPointerExceptions 和记录。或者不是?..不要忘记尝试Java 14的新功能,即使对于初学者来说它也非常有用。祝你学业顺利!
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION