Java 14 特性

按照六個月的傳統,Java 13 於2019年9月17日發布後,另一個非 LTS 版本 Java 14 計劃於2020年3月17日發布。

Java 14 功能

以下是 Java 14 的功能列表:

  • Switch 表達式(標準)- JEP 361
  • 對於 instanceof 的模式匹配(預覽)- JEP 305
  • NullPointerExceptions 的幫助 – JEP 358
  • Records(預覽)- JEP 359
  • Text Blocks(第二個預覽)- JEP 368
  • 打包工具(孵化器)- JEP 343
  • G1 的 NUMA 感知內存分配 – JEP 345
  • JFR 事件流 – JEP 349
  • 非易失性映射的字節緩衝區 – JEP 352
  • 在 macOS 上的 ZGC – JEP 364
  • 在 Windows 上的 ZGC – JEP 365
  • 外部內存訪問 API(孵化器)- JEP 370

Mac OS 上的 Java 14 安裝設置

  • 開始使用Java 14,請從這裡下載JDK。
  • 將tar文件複製並解壓縮到/Library/Java/JavaVirtualMachines中,如下所示:
$ cd /Library/Java/JavaVirtualMachines

$ sudo cp ~/Downloads/openjdk-14_osx-x64_bin.tar.gz /Library/Java/JavaVirtualMachines

$ sudo tar xzf openjdk-14_osx-x64_bin.tar.gz

$ sudo rm openjdk-14_osx-x64_bin.tar.gz

完成後,使用任何文本編輯器打開bash_profile。我使用vim ~/.bash_profile。將Java14的路徑設置為JAVA_HOME,保存更改,然後執行source ~/.bash_profile以反映更改。

export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-14.jdk/Contents/Home

最後,您可以使用Java 14編譯和運行程序。我們將使用JShell,這是一個用於快速測試新Java 14功能的交互式REPL命令行工具。

重要的是要注意,Java 14中發布的許多功能都是預覽版。這意味著雖然它們現在完全可用,但將來可能會進行修改。一些功能可能會在下一個版本中成為標準,或者被簡單地刪除。為了測試預覽功能,執行JShell或Java程序時需要明確設置--enable-preview,如下所示:

jshell --enable-preview

javac --release 14 --enable-preview Author.java

在接下來的幾節中,讓我們討論一些語言和JVM功能。

推薦閱讀在Linux上安裝Java 14

1. Switch Expressions

switch表達式在過去兩個版本中一直是一個預覽功能–Java 12和Java 13,現在終於在Java 14中獲得了永久性地位。

  • Java 12引入了用於switch表達式的lambda語法,從而允許多個案例標籤進行模式匹配,同時防止了可能導致代碼冗長的fall-throughs。它還強制執行了完整的案例,如果沒有涵蓋所有輸入案例,則會產生編譯錯誤。
  • Java 13,第二個預覽版引入了yield語句,用於從表達式返回值,而不是使用break

Java 14現在終於將這些功能定為標準了。

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

        };
System.out.println(result);
Java 14 Switch Expressions

注意:Yield並不是Java中的新關鍵字,它只是用於switch表達式中。

2. instanceof的模式匹配(預覽)

請任何Java開發人員展示他們的代碼庫,你會看到instanceof條件在整個代碼中被很好地使用。具體而言,instanceof條件檢查通常後面跟著一個類型轉換。

Java 14通過使條件提取更加簡潔來消除這種冗長性。

Java 14之前:

if (obj instanceof Journaldev) {
  Journaldev jd = (Journaldev) obj;
  System.out.println(jd.getAuthor());
}

Java 14及以後:

if (obj instanceof Journaldev jd) {
  System.out.println(jd.getAuthor());
}

在上述代碼中,只有在obj的類型為Journaldev時,實例jd才會被賦值。該變量的作用域僅限於條件塊內。

3. 有用的NullPointerExceptions

NullPointerException對於任何開發人員來說都是一場噩夢。在Java 13之前,要調試臭名昭著的NPE是棘手的。開發人員必須倚賴其他調試工具或手動找出變量/方法為null,因為堆棧跟蹤僅顯示行號。

Java 14之前:

String name = jd.getBlog().getAuthor()

//堆棧跟蹤
Exception in thread "main" java.lang.NullPointerException
    at NullPointerExample.main(NullPointerExample.java:5)

Java 14引入了一個新的JVM功能,提供更詳細的堆棧信息,如下所示:

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "Blog.getAuthor()" because the return value of "Journaldev.getBlog()" is null
    at NullPointerExample.main(NullPointerExample.java:4)

注意:上述功能不是語言特性,而是運行時環境的增強。

4. Records(預覽)

A record is a data class that stores pure data. The idea behind introducing records is to quickly create simple and concise classes devoid of boilerplate code.

通常,在Java中,一個類需要實現equals()hashCode()、getter和setter方法。儘管一些IDE支持自動生成此類,但代碼仍然冗長。使用record,您只需以以下方式定義一個類。

record Author(){}
//or
record Author (String name, String topic) {}

Java 編譯器會自動產生構造函數、私有 final 欄位、存取器、equals/hashCodetoString 方法。上述類別的自動生成 getter 方法為 name()topic()

要查看生成的程式碼,請在使用 javac 編譯程式後,使用 javap Author。下圖顯示了用於 record Author (String name, String topic) {} 的生成類別:

Javap Records Java 14

記錄的語義與 Kotlin 中的資料類別相似

此外,我們可以以以下方式為記錄添加額外的欄位、方法和構造函數:

record Author (int id, String name, String topic) {
    static int followers;

    public static String followerCount() {
        return "Followers are "+ followers;
    }

    public String description(){
        return "Author "+ name + " writes on "+ topic;
    }

    public Author{
    if (id < 0) {
        throw new IllegalArgumentException( "id must be greater than 0.");
     }
   }
}

記錄內部定義的額外構造函數稱為緊湊構造函數。它不包含任何參數,只是規範構造函數的擴展。

A compact constructor wouldn’t be generated as a separate constructor by the compiler. Instead, it is used for validation cases and would be invoked at the start of the main constructor.

關於記錄的一些重要事項:

  • A record can neither extend a class nor it can be extended by another class. It’s a final class.
  • 記錄不能是抽象的
  • 記錄不能擴展任何其他類別,也不能在主體內定義實例欄位。實例欄位必須僅在狀態描述中定義
  • 宣告的欄位為私有和 final
  • 記錄的主體允許靜態欄位和方法

推薦閱讀: Java Records

4.1) 記錄的參考字段內的值可以被改變

重要的是要注意,對於定義為對象的字段,只有參考是不可變的。底層值可以被修改。以下示例顯示了一個記錄,其中 ArrayList 被修改。正如您所看到的,每當 ArrayList 被更改時,值都會被修改。

Java 14 Records Mutable Values For References

4.2) 記錄可以實現接口

以下代碼示例展示了使用記錄實現接口的示例:以下是在 JShell 中執行上述代碼的輸出:

record Author(String name, String topic) implements Information {
  public String getFullName() {
    return "Author "+ name + " writes on " + topic;
  }
}

interface Information {
  String getFullName();
}

Java 14 Records With Interface

4.3) 記錄支持多個構造函數

記錄允許聲明多個構造函數,可以帶參數,也可以不帶參數,如下所示:

record Author(String name, String topic) {
  public Author() {

    this("NA", "NA");
  }

  public Author(String name) {

    this(name, "NA");
  }
}

4.4) 記錄允許修改存取方法

雖然記錄確實為在狀態描述中定義的字段生成公共存取方法,但它們也允許您在內容中重新定義存取方法,如下所示:

record Author(String name, String topic) {
  public String name() {
        return "This article was written by " + this.name;
    }
}

4.5) 在運行時檢查記錄及其組件

記錄為我們提供了isRecord()getRecordComponents(),以檢查該類是否為記錄,並查看其字段和類型。下面的示例顯示了實現的方式:

Java 14 Records Runtime Check

儘管在上述代碼示例中我們添加了額外的字段和方法,但請確保不要過度使用。記錄被設計為純粹的數據承載器,如果您希望實現大量額外的方法,最好還是回歸到普通類別。

5. 文本區塊(預覽)

Text Blocks 在 Java 13 中作为预览功能引入,旨在实现轻松创建多行字符串文字。它在轻松创建 HTML、JSON 或 SQL 查询字符串方面非常有用。

在 Java 14 中,Text Blocks 仍处于预览阶段,并有一些新的添加。现在我们可以使用:

  • 反斜杠来显示漂亮的多行字符串块。
  • \s 用于考虑默认情况下编译器忽略的尾随空格。它保留其前面的所有空格。
String text = """
                Did you know \
                Java 14 \
                has the most features among\
                all non-LTS versions so far\
                """;

String text2 = """
                line1
                line2 \s
                line3
                """;


String text3 = "line1\nline2 \nline3\n"

//text2 和 text3 相等。

参考资料: OpenJDK 14

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