Java 12 特性

终于,作为六个月发布周期的一部分,JDK 12来了。这是继上一个Java LTS版本11之后的一次更新。我们之前对Java 11的特性进行了详细讨论。今天我们将讨论Java 12的特性,看看它为开发者们准备了什么。Java 12于2019年3月19日发布,属于非LTS版本,因此不提供长期支持。

Java 12的特性

其中一些重要的Java 12特性包括:

  1. JVM变更 – JEP 189、JEP 346、JEP 344和JEP 230。
  2. Switch表达式
  3. 文件mismatch()方法
  4. 紧凑型数字格式
  5. 在Stream API中使用的Teeing Collectors
  6. Java字符串新方法 – indent()、transform()、describeConstable()和resolveConstantDesc()。
  7. JEP 334:JVM常量API
  8. JEP 305:instanceof的模式匹配
  9. 从JDK 12中移除了原始字符串文字。

让我们逐个查看所有这些Java 12的特性。

JVM变更

1. JEP 189 – Shenandoah:低暂停时间垃圾收集器(实验性)

RedHat启动了Shenandoah垃圾收集器,以减少GC暂停时间。其理念是与正在运行的Java线程并发地运行GC。它旨在实现一致且可预测的短暂停,与堆大小无关。因此,无论堆大小是15 MB还是15GB都无关紧要。这是Java 12中的一个实验性特性。

2. JEP 346 – G1迅速返回未使用的已分配内存

自Java 12起,G1现在将在应用程序不活动期间检查Java堆内存并将其返回给操作系统。这是一项预防性措施,用于保存和利用空闲内存。

3. JEP 344:G1中可中止的混合收集

G1 效率的改进包括使 G1 混合收集可中止,如果它们可能超过定义的暂停目标。这是通过将混合收集集合分成强制和可选两部分来实现的。因此,G1 收集器可以优先收集强制集合,以满足暂停时间目标。

4. JEP 230 和 344

微基准套件,JEP 230功能将一组基本微基准添加到 JDK 源代码中。这使得开发人员可以轻松运行现有的微基准并创建新的微基准。一个 AArch64 端口,不是两个,JEP 344,移除了所有与 arm64 端口相关的源代码,同时保留了 32 位 ARM 端口和 64 位 aarch64 端口。这使得贡献者可以将精力集中在单个 64 位 ARM 实现上。

5. JEP 341 默认 CDS 存档

这增强了 JDK 构建过程,以在 64 位平台上使用默认类列表生成类数据共享(CDS)存档。目标是改善启动时间。从 Java 12 开始,默认情况下启用了 CDS。要禁用 CDS 运行程序,请执行以下操作:

java -Xshare:off HelloWorld.java

现在,这将延迟程序的启动时间。

语言变更和特性

Java 12引入了许多语言特性。让我们看一些具体的实现。

1. Switch 表达式(预览版)

Java 12为模式匹配增强了Switch表达式。作为预览语言特性,它在JEP 325中被引入,新的语法是L ->。以下是关于Switch表达式的一些注意事项:

  • 新的语法去除了防止穿透的break语句的需要。
  • Switch表达式不再发生穿透。
  • 此外,我们可以在同一标签中定义多个常量。
  • default情况现在在Switch表达式中是强制的。
  • break用于在Switch表达式中从一个case中返回值。

经典的switch语句:

String result = "";
        switch (day) {
            case "M":
            case "W":
            case "F": {
                result = "MWF";
                break;
            }
            case "T":
            case "TH":
            case "S": {
                result = "TTS";
                break;
            }
        };

        System.out.println("Old Switch Result:");
        System.out.println(result);

有了新的Switch表达式,我们不再需要到处设置break,从而避免逻辑错误!

String result = switch (day) {
            case "M", "W", "F" -> "MWF";
            case "T", "TH", "S" -> "TTS";
            default -> {
                if(day.isEmpty())
                    break "Please insert a valid day.";
                else
                    break "Looks like a Sunday.";
            }

        };

        System.out.println(result);

让我们运行包含新Switch表达式的下面程序,使用JDK 12。

public class SwitchExpressions {

    public static void main(String[] args)
    {
        System.out.println("New Switch Expression result:");
        executeNewSwitchExpression("M");
        executeNewSwitchExpression("TH");
        executeNewSwitchExpression("");
        executeNewSwitchExpression("SUN");
    }

    public static void executeNewSwitchExpression(String day){

        String result = switch (day) {
            case "M", "W", "F" -> "MWF";
            case "T", "TH", "S" -> "TTS";
            default -> {
                if(day.isEmpty())
                    break "Please insert a valid day.";
                else
                    break "Looks like a Sunday.";
            }

        };

        System.out.println(result);
    }
}

由于这是一个预览功能,请确保已选择语言级别为 Java 12 预览。要编译上述代码,请运行以下命令:

javac -Xlint:preview --enable-preview -source 12 src/main/java/SwitchExpressions.java

运行编译程序后,我们在控制台得到以下结果:

Java Switch Expressions Program Output

Switch 表达式是一个预览语言功能。这意味着即使它是完整的,未来的 Java 版本可能不会确认它。

2. File.mismatch 方法

Java 12 添加了以下方法来比较两个文件:

public static long mismatch(Path path, Path path2) throws IOException

此方法返回第一个不匹配的位置,如果没有不匹配,则返回 -1L。两个文件可能在以下情况下不匹配:

  • 如果字节不相同。在这种情况下,返回第一个不匹配字节的位置。
  • 文件大小不相同。在这种情况下,返回较小文件的大小。

下面是从 IntelliJ Idea 给出的示例代码片段:

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

public class FileMismatchExample {

    public static void main(String[] args) throws IOException {
        Path filePath1 = Files.createTempFile("file1", ".txt");
        Path filePath2 = Files.createTempFile("file2", ".txt");
        Files.writeString(filePath1,"JournalDev Test String");
        Files.writeString(filePath2,"JournalDev Test String");

        long mismatch = Files.mismatch(filePath1, filePath2);

        System.out.println("File Mismatch position... It returns -1 if there is no mismatch");

        System.out.println("Mismatch position in file1 and file2 is >>>>");
        System.out.println(mismatch);

        filePath1.toFile().deleteOnExit();
        filePath2.toFile().deleteOnExit();

        System.out.println();

        Path filePath3 = Files.createTempFile("file3", ".txt");
        Path filePath4 = Files.createTempFile("file4", ".txt");
        Files.writeString(filePath3,"JournalDev Test String");
        Files.writeString(filePath4,"JournalDev.com Test String");

        long mismatch2 = Files.mismatch(filePath3, filePath4);

        System.out.println("Mismatch position in file3 and file4 is >>>>");
        System.out.println(mismatch2);

        filePath3.toFile().deleteOnExit();
        filePath4.toFile().deleteOnExit();



    }

}

上述 Java 程序编译并运行时的输出为:

Java File Mismatch Example Program Output

3. 紧凑型数字格式化

import java.text.NumberFormat;
import java.util.Locale;

public class CompactNumberFormatting {


    public static void main(String[] args)
    {
        System.out.println("Compact Formatting is:");
        NumberFormat upvotes = NumberFormat
                .getCompactNumberInstance(new Locale("en", "US"), NumberFormat.Style.SHORT);
        upvotes.setMaximumFractionDigits(1);

        System.out.println(upvotes.format(2592) + " upvotes");


        NumberFormat upvotes2 = NumberFormat
                .getCompactNumberInstance(new Locale("en", "US"), NumberFormat.Style.LONG);
        upvotes2.setMaximumFractionDigits(2);
        System.out.println(upvotes2.format(2011) + " upvotes");
    }


}
Java Compact Number Formatting Program Output

4. 分流收集器

分流收集器是Streams API中引入的新收集器实用程序。该收集器有三个参数 – 两个收集器和一个双函数。所有输入值都传递给每个收集器,并且结果在双函数中可用。

double mean = Stream.of(1, 2, 3, 4, 5)
                .collect(Collectors.teeing(
                        summingDouble(i -> i),
                        counting(),
                        (sum, n) -> sum / n));

System.out.println(mean);

输出为3.0

5. Java字符串新方法

Java 12中引入了4种新方法,分别是:

  • indent(int n)
  • transform(Function f)
  • Optional describeConstable()
  • String resolveConstantDesc​(MethodHandles.Lookup lookup)

要详细了解上述方法及其实现,请参阅我们的Java 12字符串方法教程。

6. JEP 334:JVM常量API

A new package java.lang.constant is introduced with this JEP. This is not that useful for those developers who don’t use constants pool.

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

另一个预览语言特性!以前将一种类型强制转换为另一种类型的旧方法是:

if (obj instanceof String) {
    String s = (String) obj;
    // 从这里开始在你的代码中使用 s
}

新方法是:

if (obj instanceof String s) {
    // 可以直接在这里使用 s
} 

这样可以节省一些不必要的类型转换。

JDK 12 中移除了原始字符串文字。

这就结束了关于 Java 12 特性的文章。

Source:
https://www.digitalocean.com/community/tutorials/java-12-features