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. 切换表达式
  3. 文件mismatch()方法
  4. 紧凑数字格式
  5. 流API中的合并收集器
  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,旨在无论堆大小如何保持一致且可预测的短暂暂停。因此,堆大小是15MB还是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源代码中添加了一个基本的微基准套件。这使开发人员能够轻松运行现有的微基准并创建新的基准。JEP 344只保留了与32位ARM端口和64位aarch64端口相关的源代码,移除了与arm64端口相关的所有源代码。这使得贡献者能够将精力集中在单个64位ARM实现上。

5. JEP 341 默认 CDS 归档

这个增强了JDK构建过程,用于在64位平台上生成一个使用默认类列表的类数据共享(CDS)存档。目标是提高启动时间。从Java 12开始,默认情况下CDS是开启的。如果要关闭CDS并运行程序,请按以下步骤操作。

java -Xshare:off HelloWorld.java

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

语言的变化和特点

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

1. 开关表达式(预览版)

Java 12对模式匹配的Switch表达式进行了加强。这个新的语法是在JEP 325中引入的,作为一种预览语言特性。以下是关于Switch表达式需要注意的一些事项:

  • 新语法消除了使用break语句来防止fallthroughs的需要。
  • Switch表达式不再发生fallthrough。
  • 此外,我们可以在同一标签中定义多个常量。
  • 在Switch表达式中,default case现在是强制性的。
  • 在Switch表达式中,break用于从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);

让我们运行包含新的 JDK 12 Switch 表达式的以下程序。

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. 文件不匹配方法

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("文件不匹配位置...如果没有不匹配则返回-1");

        System.out.println("file1和file2中的不匹配位置是 >>>>");
        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("file3和file4中的不匹配位置是 >>>>");
        System.out.println(mismatch2);

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



    }

}

当上述Java程序被编译并运行时的输出是:

Java文件不匹配示例程序输出

3. 紧凑数字格式化

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

public class CompactNumberFormatting {


    public static void main(String[] args)
    {
        System.out.println("紧凑格式化是:");
        NumberFormat upvotes = NumberFormat
                .getCompactNumberInstance(new Locale("en", "US"), NumberFormat.Style.SHORT);
        upvotes.setMaximumFractionDigits(1);

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


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


}
Java紧凑数字格式化程序输出

4. 划分收集器

Teeing Collector(分流收集器)是在 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 Constants API – JEP 334:JVM 常量 API

这个 JEP 引入了一个新包 java.lang.constant。对于不使用常量池的开发者来说,这并不是很有用。

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

另一个预览语言功能!以前将一种类型转换为另一种类型的方法是:

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

新的方式是:

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

这样做可以避免一些不必要的类型转换。

JDK 12 中已移除原始字符串字面值。

这篇文章介绍了Java 12的特性,到这里就结束了。

bannerAds