Java 12 新特性介紹

Java 12 早在 2019 年 3 月 19 日發佈,它不是一個長久支持(LTS)版本。在這之前我們已經介紹過其他版本的新特性,如果需要可以點擊下面的鏈接進行閱讀。

Switch 表達式 (JEP 325)

在 Java 12 中,對 Switch 表達式的寫法進行了改進,雖然是一個語法糖的改進,也讓 Switch 的代碼編寫變得更加優雅。先看一下在 Java 12 之前的 Switch 的寫法。

// 通過傳入月份,輸出月份所屬的季節
public static void switchJava12Before(String day) {
    switch (day) {
        case "march":
        case "april":
        case "may":
            System.out.println("春天");
            break;
        case "june":
        case "july":
        case "august":
            System.out.println("夏天");
            break;
        case "september":
        case "october":
        case "november":
            System.out.println("秋天");
            break;
        case "december":
        case "january":
        case "february":
            System.out.println("冬天");
            break;
    }
}

上面的例子中,通過傳入一個月份,輸出這個月份對應的季節。簡單的功能卻寫了大量代碼,而且每個操作都需要一個 break來防止 Case 穿透

使用預覽功能

由於 Switch 表達式在 Java 12 中並不是一個正式發佈的功能,還處於預覽測試階段,所以想要使用 Java 12 去編譯運行就需要打開功能預覽參數,當然,如果你使用的是 Java 14 以及更高版本,就可以直接跳過這個部分了。

# 編譯時
./bin/javac --enable-preview -source 12 ./Xxx.java
# 運行時
./bin/java --enable-preview Xxx

如果某個新特性是預覽功能,這意味着這個功能有可能在未來的版本中刪除

Java 12 Switch

由於 Switch 存在的上述問題,所以在 Java 12 中對 Switch 進行了改進,讓其可以使用 case L -> 的方式進行操作,那麼在 Java 12 中可以怎麼編寫這段代碼呢?

public static void switchJava12(String day) {
    switch (day) {
        case "march""april""may"            -> System.out.println("春天");
        case "june""july""august"           -> System.out.println("夏天");
        case "september""october""november" -> System.out.println("秋天");
        case "december""january""february"  -> System.out.println("冬天");
    }
}

通過測試可以得到預期的輸出結果。這還不夠,在 Switch 的改進中,還支持了使用 Switch 的返回值進行賦值。

像下面這樣:

String season = switch (day) {
    case "march""april""may"            -> "春天";
    case "june""july""august"           -> "春天";
    case "september""october""november" -> "春天";
    case "december""january""february"  -> "春天";
    default -> {
      //throw new RuntimeException("day error")
        System.out.println("day error");
        break "day error";
    }
};
System.out.println("當前季節是:" + season);

雖然編寫更加簡單了,其實這些只不過是語法糖式的更新,編譯後和之前並沒有太大區別。

文件對比 Files.mismatch

在 Java 中對於文件的操作已經在 Java 7 中進行了一次增強,這次 Java 12 又帶來了文件對比功能。對比兩個文件,如果內容一致,會返回 -1 ,如果內容不同,會返回不同的字節開始位置。

// 創建兩個文件
Path pathA = Files.createFile(Paths.get("a.txt"));
Path pathB = Files.createFile(Paths.get("b.txt"));

// 寫入相同內容
Files.write(pathA,"abc".getBytes(), StandardOpenOption.WRITE);
Files.write(pathB,"abc".getBytes(), StandardOpenOption.WRITE);
long mismatch = Files.mismatch(pathA, pathB);
System.out.println(mismatch);

// 追加不同內容
Files.write(pathA,"123".getBytes(), StandardOpenOption.APPEND);
Files.write(pathB,"321".getBytes(), StandardOpenOption.APPEND);
mismatch = Files.mismatch(pathA, pathB);
System.out.println(mismatch);

// 刪除創建的文件
pathA.toFile().deleteOnExit();
pathB.toFile().deleteOnExit();

// RESULT
// -1
// 3

對比功能的實現可以直接閱讀源碼,還是很簡單的。

Compact Number

簡化的數字格式可以直接轉換數字顯示格式,比如 1000 -> 1K,1000000 -> 1M 。

System.out.println("Compact Formatting is:");
NumberFormat upvotes = NumberFormat.getCompactNumberInstance(new Locale("en""US"), Style.SHORT);

System.out.println(upvotes.format(100));
System.out.println(upvotes.format(1000));
System.out.println(upvotes.format(10000));
System.out.println(upvotes.format(100000));
System.out.println(upvotes.format(1000000));

// 設置小數位數
upvotes.setMaximumFractionDigits(1);
System.out.println(upvotes.format(1234));
System.out.println(upvotes.format(123456));
System.out.println(upvotes.format(12345678));

可以得到輸出如下:

100
1K
10K
100K
1M
1.2K
123.5K
12.3M

JVM 相關更新

Shenandoah 垃圾收集器

Java 12 增加了 Shenandoah 一個低停頓的垃圾收集器,它可以和 Java 應用程序中的執行線程同時進行,用來收集垃圾進行內容回收,這樣就可以讓停頓時間更少。

更多關於 Shenandoah 垃圾收集器的介紹可以查看文檔:Shenandoah GC 介紹。

ZGC 併發類卸載

Z 垃圾收集器現在支持類卸載,通過卸載不使用的類來釋放這些類相關的數據結構,從而減少應用程序的總體佔用空間。因爲是併發執行,所以不會停止 Java 應用程序線程的執行,也因此對 GC 的暫停時間影響微乎其微。默認情況下啓用此功能,但可以使用命令行選項禁用-XX:-ClassUnloading

JVM 常量 API

在包 java.lang.invoke.constant 中定義了一系列的基於值的符號引用,可以用來描述各種可加載常量。可以更容易的對關鍵類文件和運行時構建的名義描述進行建模,特別是對那些從常量池中加載的常量,也讓開發者可以更簡單標準的處理可加載常量。

默認使用類數據共享(CDS)

這已經不是 JDK 第一次改進 CDS(Class Data Sharing) 功能了,CDS 可以讓 JVM 在同一臺機器或虛擬機上啓動多個應用的速度速度大大增加。原理是在啓動應用時共享一些類加載信息,這樣啓動新進程時就可以使用共享的數據。在  Java 12 之前此功能需要手動開啓,Java 12 調整爲默認開啓。

微基準套件

Java 12  中添加一套新的基於 JMH 的基本的微基準測試套件。之前也介紹過 JMH 的使用,可以參考之前文章 JMH - Java 代碼性能測試的終極利器

其他更新

1. 支持 Unicode 11

在 Java 11 支持了 Unicode 10 之後, Java 12 支持了 Unicode 11,支持操作更多的表情、符號。

文中示例已經上傳到 github/niumoo/jdk-feature

參考

[1] http://openjdk.java.net/projects/jdk/12/

[2] https://wiki.openjdk.java.net/display/shenandoah/Main

[3] http://unicode.org/versions/Unicode11.0.0/

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/V_MLtqzxa9ijgW6w6Pqocg