Java 14 開箱,它真香香香香

Java 14 已經發布有一週時間了,我準備來開個箱,和小夥伴們一起來看看新特性裏面都有哪些好玩的。我們程序員應該抱着嚐鮮、獵奇的心態,否則就容易固步自封,技術停滯不前。先來看看 Java 14 都有哪些新特性吧!

紅色線劃出來的是我比較感興趣的,其餘的對我沒什麼太大的吸引力,就暫且略過。

01、下載 JDK 14

要想開箱,得先下載 JDK 14,不然拿什麼開箱呢,對吧?有 2 處地方可供下載,Oracle 上可以下載商用版, jdk.java.net 上可以下載開源版。我們就選擇後者吧。

我目前用的是 Windows 操作系統,所以就選擇 Windows 版的 zip 包進行下載,完成後記得解壓。

02、升級 IntelliJ IDEA

需要把 IDEA 升級到搶先體驗版 2020.1 EAP,否則無法支持 Java 14 的新特性。

社區版的下載地址如下所示:

[https://www.jetbrains.com/idea/nextversion/#section=windows](https://www.jetbrains.com/idea/nextversion/#section=windows)

安裝的時候可以把之前的版本卸載,也可以選擇保留。完成後,我們來新建一個 Java 14 的項目。

01、instanceof

按照新特性的順序,我們就先從 instanceof 說起吧。舊式的 instanceof 的用法如下所示:

public class OldInstanceOf {
    public static void main(String[] args) {
        Object str = "Java 14,真香";
        if (str instanceof String) {
            String s = (String)str;
            System.out.println(s.length());
        }
    }
}

需要先使用 instanceof 在 if 條件中判斷 str 的類型是否爲 String(第一步),再在 if 語句中將 str 強轉爲字符串類型(第二步),並且要重新聲明一個變量用於強轉後的賦值(第三步)。

三個步驟也不算多,但總覺得應該還有更好的語法,這不,Java 14 就想到了這一層。

public class NewInstanceOf {
    public static void main(String[] args) {
        Object str = "Java 14,真香";
        if (str instanceof String s) {
            System.out.println(s.length());
        }
    }
}

可以直接在 if 條件判斷類型的時候添加一個變量,就不需要再強轉和聲明新的變量了。是不是特別簡潔?但模式匹配的 instanceof 在 Java 14 中是預覽版的,默認是不啓用的,所以這段代碼會有一個奇怪的編譯錯誤(Java 14 中不支持模式匹配的 instanceof)。

那怎麼解決這個問題呢?需要在項目配置中手動設置一下語言的版本。

設置完成後,編譯錯誤就隨風飄走了。程序輸出的結果如下所示:

10

不錯不錯,真香。想知道 Java 編譯器在背後幫我們做了什麼嗎?看一下反編譯後的字節碼就明白了。

public class NewInstanceOf {
    public NewInstanceOf() {
    }

    public static void main(String[] args) {
        Object str = "Java 14,真香";
        String s;
        if (str instanceof String && (s = (String)str) == (String)str) {
            System.out.println(s.length());
        }

    }
}

在 if 條件判斷前,先聲明瞭變量 s,然後在 if 條件中進行了強轉 s = (String)str),並且判斷了 s 和 str 是否相等。確實是一個解放開放者生產力的好特性,強烈希望這個特性在下個版本中轉正。

02、Records

在之前的一篇文章中,我談到了類的不可變性,它是這樣定義的:

public final class Writer {
    private final String name;
    private final int age;

    public Writer(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }
}

那麼,對於 Records 來說,一條 Record 就代表一個不變的狀態。儘管它會提供諸如 equals()hashCode()toString()、構造方法,以及字段的 getter,但它無意替代可變對象的類(沒有 setter),以及 Lombok 提供的功能。

來用 Records 替代一下上面這個 Writer 類:

public record Writer(String name, int age) { }

你看,一行代碼就搞定。關鍵是比之前的代碼功能更豐富,來看一下反編譯後的字節碼:

public final class Writer extends java.lang.Record {
    private final java.lang.String name;
    private final int age;

    public Writer(java.lang.String name, int 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 int age() /* compiled code */ }
}

類是 final 的,字段是 private final 的,構造方法有兩個參數,toString()hashCode()equals() 方法也有了,getter 方法也有了,只不過沒有 get 前綴。但是沒有 setter 方法,也就是說 Records 確實針對的是不可變對象——鑑定完畢。那怎麼使用 Records 呢?

public class WriterDemo {
    public static void main(String[] args) {
        Writer writer = new Writer("沉默王二",18);
        System.out.println("toString:" + writer);
        System.out.println("hashCode:" + writer.hashCode());
        System.out.println("name:" + writer.name());
        System.out.println("age:" + writer.age());

        Writer writer1 = new Writer("沉默王二"18);
        System.out.println("equals:" + (writer.equals(writer1)));
    }
}

程序輸出的結果如下所示:

toString:Writer[name=沉默王二, age=18]
hashCode:1130697218
name:沉默王二
age:18
equalstrue

不錯不錯,真香,以後定義不可變類時就簡單了,強烈希望這個特性在下個版本中轉正。

03、switch 表達式

關於 switch 表達式,我在之前的一篇文章中已經詳細說明了,點擊傳送門可以跳轉過去看看。兩週時間過去了,switch 表達式終於“媳婦熬成婆”,轉正了,恭喜恭喜。

記得這篇文章發表到掘金的時候,被噴子各種無腦 diss,說:“還以爲你有什麼技巧,沒想到用的是 Java 13,可我們還停留在 Java 8 啊!”這顯然是一種固步自封的心態,非常不可取,程序員不應該這樣。一個最簡單的道理就是,Java 6 當年也很經典,不是被 Java 8 取代了嗎?隨着時間的推移,Java 8 早晚會被更劃時代的新版本取代——總要進步嘛。

關於 switch 表達式,這裏就簡單地搬個例子給你瞧瞧:

public class SwitchDemo {
    enum PlayerTypes {
        TENNIS,
        FOOTBALL,
        BASKETBALL,
        PINGPANG,
        UNKNOWN
    }

    public static void main(String[] args) {
        System.out.println(createPlayer(PlayerTypes.BASKETBALL));
    }

    private static String createPlayer(PlayerTypes playerType) {
        return switch (playerType) {
            case TENNIS -> "網球運動員費德勒";
            case FOOTBALL -> "足球運動員C羅";
            case BASKETBALL -> "籃球運動員詹姆斯";
            case PINGPANG -> "乒乓球運動員馬龍";
            case UNKNOWN -> throw new IllegalArgumentException("未知");
        };
    }
}

除了可以使用 -> 的新式語法,還可以作爲 return 結果,真香。

04、Text Blocks

在文本塊(Text Blocks)出現之前,如果我們需要拼接多行的字符串,就需要很多英文雙引號和加號,看起來就好像老太婆的裹腳布,非常不雅。如果恰好要拼接一些 HTML 格式的文本(原生 SQL 也是如此)的話,還要通過空格進行排版,通過換行轉義符 \n 進行換行,這些繁瑣的工作對於一名開發人員來說,簡直就是災難。

public class OldTextBlock {
    public static void main(String[] args) {
        String html = "<html>\n" +
                "    <body>\n" +
                "        <p>Hello, world</p>\n" +
                "    </body>\n" +
                "</html>\n";
        System.out.println(html);
    }
}

Java 14 就完全不同了:

public class NewTextBlock {
    public static void main(String[] args) {
        String html = """
              <html>
                  <body>
                      <p>Hello, world</p>
                  </body>
              </html>
              "
"";
        System.out.println(html);
    }
}

多餘的英文雙引號、加號、換行轉義符,統統不見了。僅僅是通過前後三個英文雙引號就實現了。我只能說,香,它真的香!

05、鳴謝

好了,我親愛的讀者朋友,以上就是本文的全部內容了,能看到這裏的就是最優秀的程序員。原創不易,莫要白票,請你爲本文點贊個吧,這將是我寫作更多優質文章的最強動力。

如果覺得文章對你有點幫助,請微信搜索「 沉默王二 」第一時間閱讀,回覆【666】【1024】更有我爲你精心準備的 500G 高清教學視頻(已分門別類),以及大廠技術牛人整理的面經一份,本文源碼已收錄在碼雲傳送門~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章