sponsored links

從 Java 12 到 Java 17 的新特性

2021 年 9 月,Oracle 釋出了 Java 17,Java 的下一個長期支援版本。如果你在使用 Java 8 或 Java 11,可能不會注意到 Java 12 之後新增的一些很酷的新特性。

因為這是一個很重要的版本,我會突出介紹一些我個人很感興趣的新特性!

需要注意的是,Java 中的大多數變更首先需要經過“預覽”階段,也就是說它們被新增到一個版本中,但還沒有完成。人們可以嘗試使用它們,但不建議將其用在生產環境中。

這裡所列舉的所有特性都已正式新增到 Java 中,並且已經過了預覽階段。

1:封印類

在 Java 15 中處於預覽階段並在 Java 17 中成為正式特性的 封印類,提供了一種新的繼承規則限定方法。當你在類或介面前面新增 sealed 關鍵字的同時,也添加了一個允許擴充套件這個類或實現這個介面的類的清單。例如,如果你定義了一個類:

public abstract sealed class Color permits Red, Blue, Yellow

也就是說,只有 Red、Blue 和 Yellow 可以繼承這個類,其他類想要繼承它都無法透過編譯。

你也可以不使用 permits 關鍵字,然後將類定義與類放在相同的檔案中,如下所示:

public abstract sealed class Color {...}
... class Red     extends Color {...}
... class Blue    extends Color {...}
... class Yellow  extends Color {...}

注意,這些子類並不是巢狀在封印類中,而是放在類定義之後。這與使用關鍵字 permit 是一樣的效果,可以擴充套件 Color 的類只有 Red、Blue 和 Yellow。

那麼,封印類通常用在哪裡?透過限定繼承規則,同時也限定了封裝規則。假設你正在開發一個庫,並且需要將抽象類 Color 包含在其中。你知道 Color 這個類以及哪些類需要擴充套件它,但如果它被宣告為 public 的,那麼你有什麼辦法可以阻止外部程式碼擴充套件它?

如果有人誤解了它的用途並用 Square 對它進行了擴充套件,該怎麼辦?這符合你的意圖嗎?或者你其實是想讓 Color 保持私有?但即使是這樣,包級別的可見性也不能避免所有問題。如果後來有人對這個庫進行了擴充套件了該怎麼辦?他們如何能夠知道你只打算讓一小部分類整合 Color?

封印類不僅可以保護你的程式碼不受外部程式碼的影響,還是一種向你可能從未見過的人傳達意圖的方式。如果一個類是封印的,你是在傳達只有某些類可以擴充套件它。這種健壯性可以確保在多年以後任何閱讀你程式碼的人都會理解程式碼的嚴謹。

2:增強的空指標異常

增強的 空指標異常 是一個有趣的更新——不會太複雜,但仍然很受歡迎。這個增強在 Java 14 中正式釋出,提高了空指標異常 (NullPointerException,簡稱 NPE) 的可讀性,可以打印出在丟擲異常位置所呼叫的方法的名稱和空變數的名稱。例如,如果你呼叫 a.b.getName(),而 b 為空,那麼異常的堆疊跟蹤資訊會告訴你呼叫 getName() 失敗,因為 b 是空的。

我們都知道,NPE 是一種非常常見的異常,雖然在大多數情況下找出導致丟擲異常的根源並不難,但你會時不時地遇到同時有兩三個可疑變數的情況。你進入除錯模式,開始檢視程式碼,但問題很難重現。你只能試著回憶最初做了什麼導致丟擲 NPE 的。

如果你能提前獲得這些資訊,就不用這些麻煩地除錯了。這就是這個特性的閃光點:不用再猜測 NPE 是從哪裡丟擲來的。在關鍵時刻,當你遇到難以重現的異常場景時,你就有了解決問題所需的一切。

這絕對是個救星!

3:switch 表示式

希望你耐心聽我說幾句——switch 表示式(在 Java 12 中預覽,並正式新增到 Java 14 中) 是 switch 語句和 lambda 之間的某種結合。真的,當我第一次向別人描述 switch 表示式時,我的說法是他們把 switch 語句 lambda 化了。請看下面這個語法:

String adjacentColor = switch (color) {
    case Blue, Green    -> "yellow";
    case Red, Purple    -> "blue";
    case Yellow, Orange -> "red";
    default             -> "Unknown Color";
};

現在明白我的意思了嗎?

一個明顯的區別是沒有了 break 語句。switch 表示式延續了 Oracle 讓 Java 語法更簡潔的趨勢。Oracle 非常討厭大多數 switch 語句包含很多的 CASE BREAK、CASE BREAK、CASE BREAK……。

老實說,他們討厭這個是對的,因為人們很容易在這個地方犯錯。我們當中是否有人敢說他們從來沒有遇到過這種情況:忘記在 switch 裡新增 break 語句,只有當代碼在執行時發生崩潰才知道?switch 表示式透過一種有趣的方式修復了這個問題,你只需要用逗號隔開同一個程式碼塊裡所有的值。沒錯,不需要使用 break 了!它會替你處理好!

switch 表示式還新增了 yield 關鍵字。如果一個 case 進入了一個程式碼塊,yield 將被作為 switch 表示式的返回語句。例如,如果我們將上面的程式碼稍作修改:

String adjacentColor = switch (color) {
    case Blue, Green    -> "yellow";
    case Red, Purple    -> "blue";
    case Yellow, Orange -> "red";
    default             -> {
    System.out.println("The color could not be found.");
    yield "Unknown Color";
  }
};

在預設 case 裡,System.out.println() 方法將被執行,adjacentColor 變數最終的值是“Unknown Color”,因為這是 yield 返回的結果。

總的來說,switch 表示式是一種更簡潔的 switch 語句,但它不會取代 switch 語句,這兩種語句都可用。

4:文字塊

文字塊 特性在 Java 13 中預覽,並正式新增到 Java 15 中,它可以簡化多行字串的寫法,支援換行,並在不需要跳脫字元的情況下保持縮排。要建立一個文字塊,只需要這樣:

String text = """
Hello
World""";

注意,這個變數仍然是一個字串,只是它隱含了換行和製表符。同樣,如果我們想要使用引號,也不需要跳脫字元:

String text = """
You can "quote" without complaints!"""; // You can "quote" without complaints!

唯一需要使用反斜槓跳脫字元的地方是當你想要在文字塊裡包含""":

String text = """
The only necessary escape is \""",
everything else is maintained.""";

除此之外,你可以呼叫 String 的 format() 方法,用動態內容替換文字塊中的佔位符:

String name = "Chris";
String text = """
My name is %s.""".format(name); // My name is Chris.

每行後面的空格都會被剪下掉,除非你指定了'\s',這是文字塊的一個跳脫字元:

String text1 = """
No trailing spaces.
Trailing spaces.      \s""";

那麼,在什麼情況下會使用文字塊呢?除了能夠對大塊的文字進行格式化外,將程式碼片段貼上到字串中也變得非常容易。因為縮排被保留了,如果你要寫一個 HTML 或 Python 程式碼塊,或使用其他任何語言,你都可以按照正常的方式寫好它們,然後用"""把它們括起來,就可以保留程式碼的格式。你甚至可以用文字塊來編寫 JSON,並使用 format() 方法輕鬆地插入值。

總的來說,這是個一個很方便的特性。雖然文字塊看起來只是一個小功能,但從長遠來看,類似這種可以提升開發效率的小功能會逐漸增加。

5:record 類

record 類 在 Java 14 中預覽,並正式新增到 Java 16 中,是一種資料類,處理所有與 POJO 相關的樣板程式碼。也就是說,如果你聲明瞭一個 record 類:

public record Coord(int x, int y) {
}

equals() 和 hashcode() 方法會自動實現,toString() 將返回這個類例項包含的所有欄位的值,最重要的是,x() 和 y() 將分別返回 x 和 y 的值。想想你之前寫過的 POJO 類,並想象一下用 record 類來代替它們會怎樣。是不是好看多了?省了多少事了?

除此之外,record 類是 final 和不可變的——不能被繼承,並且類例項一旦被建立,它的欄位就不能被修改。你可以在 record 類中宣告方法,包括非靜態方法和靜態方法:

public record Coord(int x, int y) {
  public boolean isCenter() {
    return x() == 0 && y() == 0;
  }

  public static boolean isCenter(Coord coord) {
    return coord.x() == 0 && coord.y() == 0;
  }
}

record 類可以有多個構造器:

public record Coord(int x, int y) {
  public Coord() {
    this(0,0); // The default constructor is still implemented.
  }
}

需要注意的是,當你在 record 類中宣告自定義建構函式時,必須呼叫預設建構函式。否則,record 類將不知道如何處理它的值。如果你聲明瞭一個與預設建構函式一樣的建構函式,你要初始化所有的欄位:

public record Coord(int x, int y) {
  public Coord(int x, int y) {
    this.x = x;
    this.y = y;
  } // Will replace the default constructor.
}

關於 record 類,有很多可討論的話題。這是一個大的變更,在合適的地方使用它們,它們會非常有用。我在這裡沒有涵蓋所有內容,但希望這能讓你瞭解它們所提供的能力。

6:模式匹配

模式匹配 是 Oracle 在與 Java 冗長語法的鬥爭中做出的另一個舉措。模式匹配在 Java 14 和 Java 15 中預覽過,並正式新增到 Java 16 中,它可以在 instanceof 條件得到滿足後消除不必要的型別轉換。例如,我們都很熟悉這樣的程式碼:

if (o instanceof Car) {
  System.out.println(((Car) o).getModel());
}

如果你想要訪問 Car 的方法,必要要這麼做。在第二行,o 是 Car 的例項,這是毫無疑問的,instanceof 已經確認了這一點。如果我們使用模式匹配,只要做一個小小的改變:

if (o instanceof Car c) {
  System.out.println(c.getModel());
}

現在,所有的物件型別轉換都由編譯器完成。看起來改變很小,但它避免了很多樣板程式碼。這也適用於條件分支,當你進入一個已經明確了物件型別的分支:

if (!(o instance of Car c)) {
  System.out.println("This isn't a car at all!");
} else {
  System.out.println(c.getModel());
}

你甚至可以在 instanceof 那一行使用模式匹配:

public boolean isHonda(Object o) {
  return o instanceof Car c && c.getModel().equals("Honda");
}

雖然模式匹配不像其他一些變更那麼大,但還是簡化了常用的程式碼。

分類: 情感
時間: 2022-02-08

相關文章

老哥倆跨越50年的中秋團圓

老哥倆跨越50年的中秋團圓
又是一年中秋節,家家戶戶共團圓.今年因伯母身體有恙,伯父沒有回老家居住.不由讓我想起2019年,那個跨越50年的中秋團圓. 當時我放假,正好孃家落花生,我在孃家住了幾天,老公在家陪伴患病的公公.中秋節 ...

一門心思玩爛網遊是種怎樣的體驗?

一門心思玩爛網遊是種怎樣的體驗?
<最終幻想14>這類出色的MMORPG都有一些特別之處,比如擁有引人入勝的故事.設計精妙的任務,以及能促使玩家交友的社群.同樣,糟糕網遊往往也有與眾不同的地方,包括玩法沉悶.故障頻出.貪婪 ...

行動硬碟要怎麼買才划算?會玩的都選擇自制行動硬碟,你呢?

行動硬碟要怎麼買才划算?會玩的都選擇自制行動硬碟,你呢?
行動硬碟要怎麼買才划算? 面對這樣的一個問題,相信不少小夥伴要呵呵一笑:"買個行動硬碟還有講究嗎?不就擴充套件容量",別搞得那麼複雜,直接上成品行動硬碟不就得了!不...眼下還有第 ...

“老戲骨”曹翠芬:人到中年爆紅,與演員丈夫相愛一生卻有遺憾

“老戲骨”曹翠芬:人到中年爆紅,與演員丈夫相愛一生卻有遺憾
點選關注,每天都有名人故事感動您! 曹翠芬 1993年,著名女星曹翠芬因出演26集民國勵志劇<上海一家人>,榮獲第12屆中國電視劇"飛天獎"最佳女配角獎.1995年,她 ...

年紀輕輕手腳冰涼:成為冷女人的正是這4種日常行為

年紀輕輕手腳冰涼:成為冷女人的正是這4種日常行為
很多女人不明白這樣一個事實:男人抽菸.喝酒.無肉不歡.熬夜.縱慾,為什麼得病的少,我不抽菸不喝酒不熬夜不縱慾肉也吃得少,為什麼反而百病纏身?這或許是每個女人都應該鄭重思考的問題,上蒼賜予男人們香菸美酒 ...

什麼是真正的偶像劇鼻祖?這8位瓊瑤小生稱霸一時,秒殺小鮮肉

什麼是真正的偶像劇鼻祖?這8位瓊瑤小生稱霸一時,秒殺小鮮肉
說到瓊瑤小生,大家腦海裡可能會立刻浮現很多人的面孔,那一群曾經風靡無數少女的瓊瑤小生們是一代人的夢中情人. 他們是瓊瑤編織的美夢中的夢幻男神,今天想刊刊就帶大家回到那個夢開始的地方,咱們一起去看看曾經 ...

#海南機車節# 六旬機車“發燒友”梁有學:偏愛速度與激情 騎出年輕開朗的心態

#海南機車節# 六旬機車“發燒友”梁有學:偏愛速度與激情 騎出年輕開朗的心態
編者按:與其來一場說走就走的旅行,倒不如擁有一次說走就走的騎行.一路走走停停也好,極速狂飆也罷,只有在機車中,才能體現得淋漓盡致.今年10月,海南將邂逅一場機車的"盛宴",你準備好 ...

肖玉璧嫌官太小,讓毛主席數他身上有多少傷疤,毛主席如何回應?

肖玉璧嫌官太小,讓毛主席數他身上有多少傷疤,毛主席如何回應?
一名紅軍戰士在警衛員的帶領下進入毛主席辦公的窯洞內,一進去就氣沖沖的說:"主席,我好不容易身體痊癒了,現在卻把我調到稅務所當主任,這不是大材小用嘛!" 主席看著他生氣的樣子笑呵呵的 ...

網友們在舊貨店發現的各種寶貝!一個比一個驚喜哇…

網友們在舊貨店發現的各種寶貝!一個比一個驚喜哇…
話說,有些人逛舊貨店是為了省錢,還有些人則把它當成是一種"尋寶"的旅程,專門去發掘那些便宜又有趣的東東- 比如下面這些國外網友分享的經歷,看完不得不感慨,在那些被人遺忘的角落,總是 ...

看完黃奕的生日感言,明悟了很現實的人生哲理:別活在過去

看完黃奕的生日感言,明悟了很現實的人生哲理:別活在過去
黃奕的生日感言 自從前夫"偷雞不成蝕把米",舉報別人反而把自己送進監獄後,黃奕的好日子就來了,現在的時光對於她而言也是幸福無比的,因此連今年的生日都辦得特別隆重且甜蜜.但是作為圈內 ...

《牧馬人》公映39年:4大主演有人離世,有人離婚,有人沉寂

《牧馬人》公映39年:4大主演有人離世,有人離婚,有人沉寂
點選關注,每天都有名人故事感動您! <牧馬人>海報 1982年,由著名導演謝晉執導,上海電影製片廠出品的影片<牧馬人>,在全國隆重公映,該片被公認為世紀經典影片,當年引起巨大反 ...

四大天王的收入現狀:混的最好最窮,混的最不好的卻最富有

四大天王的收入現狀:混的最好最窮,混的最不好的卻最富有
每個年代,都有著代表的偶像,像80年代的偶像,呼聲最高的,應該就是四大天王了,所謂的四大天王,就是劉德華.張學友.郭富城.黎明這四個人,當時他們的名氣非常的高,有才華.有演技,關鍵是人長得賊帥,不知道 ...

開著車齡26年、里程61萬公里的車子出門是什麼體驗?

開著車齡26年、里程61萬公里的車子出門是什麼體驗?
[有車以後 編輯體驗]說起老皇冠,我相信很多人多多少少都能和它扯上一點關係吧.它可能是家裡的車,可能是親朋好友的車,可能是在日本.香港旅遊時坐過的計程車?而我與皇冠的故事,在我出生前就已經展開了,因為 ...

好惶惑,好多人問為啥把四喜送人,為啥送人的是四喜不是三花?

好惶惑,好多人問為啥把四喜送人,為啥送人的是四喜不是三花?
前兩天寫了送走四喜的心情,沒想到有那麼的朋友關心四喜,好多人問為啥把四喜送人,為啥送人的是四喜不是三花?唉,事有緩急,貓有參差,人有無奈,不知道我這樣想的對不對: 四喜是個美短虎斑,公貓,已經做過絕育 ...

常在河邊走溼鞋了——花開杏壇之是可忍孰不可忍

常在河邊走溼鞋了——花開杏壇之是可忍孰不可忍
<花開杏壇>原創連載 第二十八章 是可忍孰不可忍 以前還是真沒想到教書育人的這麼高尚的群體裡頭什麼鳥都有,不過後來,隨著實習的深入也慢慢的知道了老馬這隻鳥的底細. 老馬原來是在博興縣一個鄉 ...

這才是真實的十月鄉村,純樸而美好,看後彷彿回了一次老家

這才是真實的十月鄉村,純樸而美好,看後彷彿回了一次老家
圖文:紅豔 在我的眼裡,這才是蘇北真實的十月鄉村,每張畫面都是那樣純樸而美好,看後彷彿回了一次老家! 國慶節日的這些天,蘇北農村迎來了婚嫁的高峰期,幾乎每天都能聽到放炮的聲音,外出走走,不經意間就會看 ...

初中老師和一個學生的對話
今天週末,但是住宿班正常上課.下午計算機課內容是windows操作.有一個班的孩子在我講課的時候,幾乎快躺在椅子上了.根本不看螢幕,我喊了他兩次,他才勉強坐直了.等到課講完了,佈置了十道操作題.我規定 ...

民間故事:富商買包子送給和尚,當天兩兒子身亡,別人:是報應

民間故事:富商買包子送給和尚,當天兩兒子身亡,別人:是報應
張堅看著兩位兒子的屍體就這樣躺在自己面前,心中是悲痛萬般,怪自己為什麼要那樣做?妻子這時候反倒平靜了下來,獨自走進房間 明朝萬曆年間,清水鎮有一富商,姓張名堅,他家世代都是經商的,家財萬貫,但這人有一 ...

2萬買30萬改的高爾夫4,玩老車你需要準備什麼?

2萬買30萬改的高爾夫4,玩老車你需要準備什麼?
問一個問題,2萬塊收一臺14年車齡的老高爾夫4,你會花超過30萬來玩這臺老車麼?我相信很多人都會拒絕,30萬我買一臺寶馬3系.賓士C不香麼?或者說玩車,我買一臺思域在花10萬改不香麼? 說是這麼說,但 ...

適合長期玩下去的老遊戲,獻給想找遊戲慢慢玩的80、90後玩家

適合長期玩下去的老遊戲,獻給想找遊戲慢慢玩的80、90後玩家
Hello,大家好,我是那個又菜又愛玩的舞文,今天來為大家推薦一些,適合大部分80和90後老玩家長期玩下去的經典老遊戲.考慮到大多數80和90後玩家,都因為工作.事業.家庭等多方面原因,玩遊戲的時間並 ...