Java14:你須要知道的新特性

基本介紹

2020 年 3 月 17 日,JDK / Java 14 正式 GA(General Available)。這是自從 Java 採用六個月一次的發佈週期以後的第五次發佈。html

此版本包含的 JEP Java/JDK Enhancement Proposals JDK 加強提案)比 Java 12 和 13 加起來的還要多。總共 16 個新特性,包括兩個孵化器模塊 、三 個預覽特性、兩個棄用的功能以及兩個刪除的功能。java

  • 「孵化器模塊」:將 還沒有定稿的 API 和工具先交給開發者使用,以得到反饋,並用這些反饋進一步改進 Java 平臺的質量。
  • 「預覽特性」:是規格已經成型、實現已經肯定,但還未最終定稿的功能。它們出如今 Java 中的目的是收集在真實世界中使用後的反饋信息,促進這些功能的最終定稿 。這些特性可能會隨時改變,根據反饋結果, 這些特性甚至可能會被移除,但一般全部預覽特性最後都會在 Java 中固定下來。

環境準備

安裝 JDK 14 https://www.oracle.com/technetwork/java/javase/overview/index.html程序員

安裝編譯器:IDEA 2020.1 或者 Eclipse 2020-03sql

新特性介紹

JEP 305:instanceof 的模式匹配(預覽特性)

這個特性頗有意思,由於它爲更爲通用的模式匹配打開了大門。模式匹配經過更爲簡便的語法基於必定的條件來抽取對象的組件,而 instanceof 恰好是這種狀況,它先檢查對象類型,而後再調用對象的方法或訪問對象的字段。macos

在 Java 14 以前,咱們使用 instanceof 是這樣的windows

@Test
public void test01() {
    Object obj = "hello java14";
    if (obj instanceof String) {
        String str = (String) obj;
        System.out.println(str.contains("hello"));
    } else {
        System.out.println("不是 String 類型");
    }
}

在 Java 14 中是這樣的,至關於將上面的第四、5行代碼簡化了,省略了強制轉化的過程,注意:「str 的做用域依舊是 if 結構內」數組

@Test
public void test02() {
    Object obj = "hello java14";
    if (obj instanceof String str) {
        System.out.println(str.contains("hello"));
    } else {
        System.out.println("不是 String 類型");
    }
}

有了該功能,能夠減小 Java 程序中顯式強制轉換的數量,從而提升生產力,還能實現更精確、簡潔的類型安全的代碼 。安全

JEP 358:很是實用的 NullPointerException

該特性改進了 NullPointerException 的可讀性,能更準確地給出 null 變量的信息 。併發

就是這個老爺子當年發明的 null,讓成千上萬的程序員深惡痛絕,他稱本身犯了一個價值十億美金的錯誤,那就是空指針!oracle

《Java 8 實戰》中是這樣說的:

  • 它是錯誤之源。 NullPointerException 是目前 Java 程序開發中最典型的異常。它會使你的代碼膨脹。
  • 它讓你的代碼充斥着深度嵌套的 null 檢查,代碼的可讀性糟糕透頂。
  • 它自身是毫無心義的。 null 自身沒有任何的語義, 尤爲是 它表明的是在靜態類型語言中以一種錯誤的方式對缺失變量值的建模。
  • 它破壞了 Java 的哲學。 Java 一直試圖避免讓程序員意識到指針的存在,惟一的例外是:null 指針。
  • 它在 Java 的類型系統上開了個口子。 null 並不屬於任何類型,這意味着它能夠被賦值給任意引用類型的變量。這會致使問題, 緣由是當這個變量被傳遞到系統中的另外一個部分後,你將沒法獲知這個 null 變量最初賦值究竟是什麼類型。

在 Java 8 中引入了 Optional,Optional 在可能爲 null 的對象上作了一層封裝,強制你思考值不存在的狀況,這樣
就能避免潛在的空指針異常 。

在 Java 14 中,對於 NPE 有了一個加強,該特性能夠更好地提示哪一個地方出現的空指針

須要咱們在運行參數上加上 -XX:+ShowCodeDetailsInExceptionMessages 開啓此功能,這個加強特性不只適用於方法調用,只要會致使 NullPointerException 的地方也都適用,包括字段的訪問、數組的訪問和賦值 。

JEP 359:Record (預覽特性)

咱們有時候須要編寫許多低價值的重複代碼來實現一個簡單的數據載體類:構造函數,訪問器,equals()、hashCode()、toString() 等。爲了不這種重複代碼,Java 14 推出了 record 。

該預覽特性提供了一種更爲緊湊的語法來聲明類。 值得一提的是,該特性能夠大幅減小定義相似數據類型時所需的樣板代碼。

使用 record 來減小類聲明語法,效果相似 lombok 的 @Data 註解, Kotlin 中的 data class 。它們的共同點是類的部分或所有狀態能夠直接在類頭中描述,而且這個類中只包含了純數據而已。

咱們聲明一個 record 類型的類

public record Person(String name, Integer age) {
}

它編譯後的 class 文件以下

public final class Person extends java.lang.Record {
    private final java.lang.String name;
    private final java.lang.Integer age;

    public Person(java.lang.String name, java.lang.Integer age) { /* compiled code */ }

    public java.lang.String toString() { /* compiled code */ }

    public final int hashCode() { /* compiled code */ }

    public final boolean equals(java.lang.Object o) { /* compiled code */ }

    public java.lang.String name() { /* compiled code */ }

    public java.lang.Integer age() { /* compiled code */ }
}

調用其屬性的時候與普通類有所不一樣

@Test
public void test3(){
    Person person = new Person("張三", 12);
    person.name();
    person.age();
}

當你用 record 聲明一個類時,該類將自動擁有如下功能:

  • 獲取成員變量的簡單方法,以上面代碼爲例 name() 和 partner() 。注意區別於咱們日常 getter 的寫法。
  • 一個 equals 方法的實現,執行比較時會比較該類的全部成員屬性
  • 重寫 equals 固然要重寫 hashCode
  • 一個能夠打印該類全部成員屬性的 toString 方法。
  • 請注意只會有一個構造方法。

和枚舉類型同樣,記錄也是類的一種受限形式。 做爲回報,記錄對象在簡潔性方面提供了顯著的好處。

可是須要注意:

  • 能夠在 Record 聲明的類中定義靜態字段、靜態方法、構造器或實例方法。
  • 不能在 Record 聲明的類中定義實例字段;類不能聲明爲 abstract;不能聲明顯式的父類等。

JEP 361:switch 表達式

這是 JDK 12 和 JDK 13 中的預覽特性,如今是正式特性了。

咱們使用 -> 來替代之前的 :break,另外還提供了 yield 來在 block 中返回值

代碼演示:

public class SwitchExpression {
    public static void main(String[] args) {
        Season type = Season.AUTUMN;
        String s = switch (type) {
            case SPRING -> "春";
            case SUMMER -> "夏";
            case AUTUMN -> "秋";
            case WINTER -> "冬";
            default -> {
                System.out.println("沒有" + type + "這個選項");
                yield "error";
            }
        };
    }
    enum Season {
        SPRING, SUMMER, AUTUMN, WINTER
    }
}

JEP 368:文本塊(預覽第二版)

在 Java 中,一般須要使用 String 類型表達 HTML XML SQL 或 JSON 等格式的字符串,在進行字符串賦值時須要進行轉義和鏈接操做,而後才能編譯該代碼,但這種表達方式難以閱讀而且難以維護。

因而在 JDK13 中引入了 text blocks,JDK 14 進行了第二輪 preview,JDK14 的版本主要增長了兩個功能,分別是\\s

例如咱們要寫一個 sql 語句,使用普通的字符串是這樣的,這是比較簡單的語句,若是複雜一點,簡直不堪入目

@Test
public void test1() {
    String sql =
        "SELECT name, age\n" +
        "FROM user\n" +
        "WHERE age = 19";
    System.out.println(sql);
}

使用了代碼塊是這樣的,可讀性變高了

@Test
public void test2(){
    String sql = """
            SELECT name, age
            FROM user
            WHERE age = 19
            """;
    System.out.println(sql);
}

可是運行上述代碼能夠看出,代碼塊裏寫的是什麼格式就會輸出什麼格式,若是咱們想讓它只輸出一行,可讀性也高呢?

這時,咱們可使用 JDK 14 新加的 \(取消換行)和 \s(一個空格)

@Test
public void test3(){
    String sql = """
            SELECT name, age \
            FROM user\s\
            WHERE age = 19\s\
            """;
    System.out.println(sql);
}

JEP 366 :棄用 ParallelScavenge 和 SerialOld GC 組合

JDK 官方給出將這個 GC 組合標記爲 Deprecate 的理由是:這個 GC 組合須要大量的代碼維護工做,而且,這個 GC 組合不多被使用。由於它的使用場景應該是一個很大的 Young 區配合一個很小的 Old 區,這樣的話, Old 區用 SerialOldGC 去收集時停頓時間咱們才能勉強接受 。

廢棄了 parallel young generation GC 與 SerialOld GC 的組合( XX:+UseParallelGC 與 XX: UseParallelOldGC 配合開啓 ),如今使用 -XX:+UseParallelGC -XX:-UseParallelOldGC 或者 -XX:-UseParallelOldGC 都會出現以下警告:

Java HotSpot(TM) 64 Bit Server VM warning: Option UseParallelOldGC was deprecated in version 14.0 and will likely be removed in a future release.

JEP 363 :刪除 CMS 垃圾回收器

該來的總會來,自從 G1 基於 Region 分代 )橫空 出世後, CMS 在 JDK9 中就被標記爲 Deprecate 了( JEP 291: Deprecate the Concurrent Mark Sweep (CMS) Garbage Collector)

CMS 的弊端:

  1. 會產生內存碎片,致使併發清除後,用戶線程可用的空間不足 。
  2. 既然強調了併發( Concurrent),CMS 收集器 對 CPU 資源很是敏感。
  3. CMS 收集器沒法處理浮動垃圾

上述的這些問題,尤爲是碎片化問題,給你的 JVM 實例就像埋了一顆炸彈。說不定哪次就在你的業務高峯期來一次 FGC。當 CMS 中止工做時,會把 Serial Old GC 做爲備選方案,而 Serial Old GC 是 JVM 中性能最差的垃圾回收方式,停頓個幾秒鐘,上十秒都有可能 。

移除了 CMS 垃圾收集器,若是在 JDK14 中使用 XX:+UseConcMarkSweepGC 的話,JVM 不會報錯,只是給出一個 warning 信息。

JEP:ZGC on macOS and windows

先看一下 ZGC 的恐怖性能,它能夠在儘量對吞吐量影響不大的前提下,實如今任意堆內存大小下均可以把垃圾收集的停頓時間限制在十毫秒之內的低延遲。

JEP 364:ZGC 應用在 macOS 上、JEP 365:ZGC 應用在 Windows 上

JDK14 以前, ZGC 僅 Linux 才支持 。儘管許多使用 ZGC 的用戶都使用類 Linux 的環境,但在 Windows 和 macOS 上,人們也須要 ZGC 進行開發部署和測試。許多桌面應用也能夠從 ZGC 中受益。所以, ZGC 特性被移植到了 Windows 和 macOS 上。

使用方式:-XX:+UnlockExperimentalVMOptions -XX:+UseZGC

雖然 ZGC 還在試驗狀態,沒有完成全部特性,但此時性能已經至關亮眼,用「使人震驚、革命性」來形容,不爲過。將來將在服務端、大內存、低延遲應用的首選垃圾收集器。


有幾個不重要的新特性沒有列舉,可自行查看相關資料

本文大部分的資料來源於此視頻的課件:https://www.bilibili.com/video/BV1tC4y147US

相關文章
相關標籤/搜索