<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          從 Java 12 到 Java 17 那些激動(dòng)人心的新特性

          共 5948字,需瀏覽 12分鐘

           ·

          2022-01-23 16:52

          2021 年 9 月,Oracle 發(fā)布了 Java 17,Java 的下一個(gè)長(zhǎng)期支持版本。如果你在使用 Java 8 或 Java 11,可能不會(huì)注意到 Java 12 之后新增的一些很酷的新特性。


          因?yàn)檫@是一個(gè)很重要的版本,我會(huì)突出介紹一些我個(gè)人很感興趣的新特性!


          需要注意的是,Java 中的大多數(shù)變更首先需要經(jīng)過(guò)“預(yù)覽”階段,也就是說(shuō)它們被添加到一個(gè)版本中,但還沒(méi)有完成。人們可以嘗試使用它們,但不建議將其用在生產(chǎn)環(huán)境中。


          這里所列舉的所有特性都已正式添加到 Java 中,并且已經(jīng)過(guò)了預(yù)覽階段。


          ?1:封印類


          在 Java 15 中處于預(yù)覽階段并在 Java 17 中成為正式特性的 封印類,提供了一種新的繼承規(guī)則限定方法。當(dāng)你在類或接口前面添加 sealed 關(guān)鍵字的同時(shí),也添加了一個(gè)允許擴(kuò)展這個(gè)類或?qū)崿F(xiàn)這個(gè)接口的類的清單。例如,如果你定義了一個(gè)類:


          public?abstract?sealed class?Color?permits?Red, Blue, Yellow


          也就是說(shuō),只有 Red、Blue 和 Yellow 可以繼承這個(gè)類,其他類想要繼承它都無(wú)法通過(guò)編譯。


          你也可以不使用 permits 關(guān)鍵字,然后將類定義與類放在相同的文件中,如下所示:


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


          注意,這些子類并不是嵌套在封印類中,而是放在類定義之后。這與使用關(guān)鍵字 permit 是一樣的效果,可以擴(kuò)展 Color 的類只有 Red、Blue 和 Yellow。


          那么,封印類通常用在哪里?通過(guò)限定繼承規(guī)則,同時(shí)也限定了封裝規(guī)則。假設(shè)你正在開(kāi)發(fā)一個(gè)庫(kù),并且需要將抽象類 Color 包含在其中。你知道 Color 這個(gè)類以及哪些類需要擴(kuò)展它,但如果它被聲明為 public 的,那么你有什么辦法可以阻止外部代碼擴(kuò)展它?


          如果有人誤解了它的用途并用 Square 對(duì)它進(jìn)行了擴(kuò)展,該怎么辦?這符合你的意圖嗎?或者你其實(shí)是想讓 Color 保持私有?但即使是這樣,包級(jí)別的可見(jiàn)性也不能避免所有問(wèn)題。如果后來(lái)有人對(duì)這個(gè)庫(kù)進(jìn)行了擴(kuò)展了該怎么辦?他們?nèi)绾文軌蛑滥阒淮蛩阕屢恍〔糠诸惣?Color?


          封印類不僅可以保護(hù)你的代碼不受外部代碼的影響,還是一種向你可能從未見(jiàn)過(guò)的人傳達(dá)意圖的方式。如果一個(gè)類是封印的,你是在傳達(dá)只有某些類可以擴(kuò)展它。這種健壯性可以確保在多年以后任何閱讀你代碼的人都會(huì)理解代碼的嚴(yán)謹(jǐn)。


          2:增強(qiáng)的空指針異常


          增強(qiáng)的 空指針異常 是一個(gè)有趣的更新——不會(huì)太復(fù)雜,但仍然很受歡迎。這個(gè)增強(qiáng)在 Java 14 中正式發(fā)布,提高了空指針異常 (NullPointerException,簡(jiǎn)稱 NPE) 的可讀性,可以打印出在拋出異常位置所調(diào)用的方法的名稱和空變量的名稱。例如,如果你調(diào)用 a.b.getName(),而 b 為空,那么異常的堆棧跟蹤信息會(huì)告訴你調(diào)用 getName() 失敗,因?yàn)?b 是空的。


          我們都知道,NPE 是一種非常常見(jiàn)的異常,雖然在大多數(shù)情況下找出導(dǎo)致拋出異常的根源并不難,但你會(huì)時(shí)不時(shí)地遇到同時(shí)有兩三個(gè)可疑變量的情況。你進(jìn)入調(diào)試模式,開(kāi)始查看代碼,但問(wèn)題很難重現(xiàn)。你只能試著回憶最初做了什么導(dǎo)致拋出 NPE 的。


          如果你能提前獲得這些信息,就不用這些麻煩地調(diào)試了。這就是這個(gè)特性的閃光點(diǎn):不用再猜測(cè) NPE 是從哪里拋出來(lái)的。在關(guān)鍵時(shí)刻,當(dāng)你遇到難以重現(xiàn)的異常場(chǎng)景時(shí),你就有了解決問(wèn)題所需的一切。


          這絕對(duì)是個(gè)救星!


          3:switch 表達(dá)式


          希望你耐心聽(tīng)我說(shuō)幾句——switch 表達(dá)式(在 Java 12 中預(yù)覽,并正式添加到 Java 14 中) 是 switch 語(yǔ)句和 lambda 之間的某種結(jié)合。真的,當(dāng)我第一次向別人描述 switch 表達(dá)式時(shí),我的說(shuō)法是他們把 switch 語(yǔ)句 lambda 化了。請(qǐng)看下面這個(gè)語(yǔ)法:


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


          現(xiàn)在明白我的意思了嗎?


          一個(gè)明顯的區(qū)別是沒(méi)有了 break 語(yǔ)句。switch 表達(dá)式延續(xù)了 Oracle 讓 Java 語(yǔ)法更簡(jiǎn)潔的趨勢(shì)。Oracle 非常討厭大多數(shù) switch 語(yǔ)句包含很多的 CASE BREAK、CASE BREAK、CASE BREAK……。


          老實(shí)說(shuō),他們討厭這個(gè)是對(duì)的,因?yàn)槿藗兒苋菀自谶@個(gè)地方犯錯(cuò)。我們當(dāng)中是否有人敢說(shuō)他們從來(lái)沒(méi)有遇到過(guò)這種情況:忘記在 switch 里添加 break 語(yǔ)句,只有當(dāng)代碼在運(yùn)行時(shí)發(fā)生崩潰才知道?switch 表達(dá)式通過(guò)一種有趣的方式修復(fù)了這個(gè)問(wèn)題,你只需要用逗號(hào)隔開(kāi)同一個(gè)代碼塊里所有的值。沒(méi)錯(cuò),不需要使用 break 了!它會(huì)替你處理好!


          switch 表達(dá)式還新增了 yield 關(guān)鍵字。如果一個(gè) case 進(jìn)入了一個(gè)代碼塊,yield 將被作為 switch 表達(dá)式的返回語(yǔ)句。例如,如果我們將上面的代碼稍作修改:


          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";
          ??}
          };


          在默認(rèn) case 里,System.out.println() 方法將被執(zhí)行,adjacentColor 變量最終的值是“Unknown Color”,因?yàn)檫@是 yield 返回的結(jié)果。


          總的來(lái)說(shuō),switch 表達(dá)式是一種更簡(jiǎn)潔的 switch 語(yǔ)句,但它不會(huì)取代 switch 語(yǔ)句,這兩種語(yǔ)句都可用。


          4:文本塊


          文本塊 特性在 Java 13 中預(yù)覽,并正式添加到 Java 15 中,它可以簡(jiǎn)化多行字符串的寫(xiě)法,支持換行,并在不需要轉(zhuǎn)義字符的情況下保持縮進(jìn)。要?jiǎng)?chuàng)建一個(gè)文本塊,只需要這樣:


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


          注意,這個(gè)變量仍然是一個(gè)字符串,只是它隱含了換行和制表符。同樣,如果我們想要使用引號(hào),也不需要轉(zhuǎn)義字符:


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


          唯一需要使用反斜杠轉(zhuǎn)義字符的地方是當(dāng)你想要在文本塊里包含""":


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


          除此之外,你可以調(diào)用 String 的 format() 方法,用動(dòng)態(tài)內(nèi)容替換文本塊中的占位符:


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


          每行后面的空格都會(huì)被剪切掉,除非你指定了'\s',這是文本塊的一個(gè)轉(zhuǎn)義字符:


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


          那么,在什么情況下會(huì)使用文本塊呢?除了能夠?qū)Υ髩K的文本進(jìn)行格式化外,將代碼片段粘貼到字符串中也變得非常容易。因?yàn)榭s進(jìn)被保留了,如果你要寫(xiě)一個(gè) HTML 或 Python 代碼塊,或使用其他任何語(yǔ)言,你都可以按照正常的方式寫(xiě)好它們,然后用"""把它們括起來(lái),就可以保留代碼的格式。你甚至可以用文本塊來(lái)編寫(xiě) JSON,并使用 format() 方法輕松地插入值。


          總的來(lái)說(shuō),這是個(gè)一個(gè)很方便的特性。雖然文本塊看起來(lái)只是一個(gè)小功能,但從長(zhǎng)遠(yuǎn)來(lái)看,類似這種可以提升開(kāi)發(fā)效率的小功能會(huì)逐漸增加。


          5:record 類


          record 類 在 Java 14 中預(yù)覽,并正式添加到 Java 16 中,是一種數(shù)據(jù)類,處理所有與 POJO 相關(guān)的樣板代碼。也就是說(shuō),如果你聲明了一個(gè) record 類:


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

          }


          equals() 和 hashcode() 方法會(huì)自動(dòng)實(shí)現(xiàn),toString() 將返回這個(gè)類實(shí)例包含的所有字段的值,最重要的是,x() 和 y() 將分別返回 x 和 y 的值。想想你之前寫(xiě)過(guò)的 POJO 類,并想象一下用 record 類來(lái)代替它們會(huì)怎樣。是不是好看多了?省了多少事了?


          除此之外,record 類是 final 和不可變的——不能被繼承,并且類實(shí)例一旦被創(chuàng)建,它的字段就不能被修改。你可以在 record 類中聲明方法,包括非靜態(tài)方法和靜態(tài)方法:


          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 類可以有多個(gè)構(gòu)造器:

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


          需要注意的是,當(dāng)你在 record 類中聲明自定義構(gòu)造函數(shù)時(shí),必須調(diào)用默認(rèn)構(gòu)造函數(shù)。否則,record 類將不知道如何處理它的值。如果你聲明了一個(gè)與默認(rèn)構(gòu)造函數(shù)一樣的構(gòu)造函數(shù),你要初始化所有的字段:


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


          關(guān)于 record 類,有很多可討論的話題。這是一個(gè)大的變更,在合適的地方使用它們,它們會(huì)非常有用。我在這里沒(méi)有涵蓋所有內(nèi)容,但希望這能讓你了解它們所提供的能力。


          6:模式匹配


          模式匹配 是 Oracle 在與 Java 冗長(zhǎng)語(yǔ)法的斗爭(zhēng)中做出的另一個(gè)舉措。模式匹配在 Java 14 和 Java 15 中預(yù)覽過(guò),并正式添加到 Java 16 中,它可以在 instanceof 條件得到滿足后消除不必要的類型轉(zhuǎn)換。例如,我們都很熟悉這樣的代碼:


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


          如果你想要訪問(wèn) Car 的方法,必要要這么做。在第二行,o 是 Car 的實(shí)例,這是毫無(wú)疑問(wèn)的,instanceof 已經(jīng)確認(rèn)了這一點(diǎn)。如果我們使用模式匹配,只要做一個(gè)小小的改變:


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


          現(xiàn)在,所有的對(duì)象類型轉(zhuǎn)換都由編譯器完成。看起來(lái)改變很小,但它避免了很多樣板代碼。這也適用于條件分支,當(dāng)你進(jìn)入一個(gè)已經(jīng)明確了對(duì)象類型的分支:


          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");
          }


          雖然模式匹配不像其他一些變更那么大,但還是簡(jiǎn)化了常用的代碼。


          Java 17 將繼續(xù)演進(jìn)


          當(dāng)然,Java 12 到 Java 17 并不是只推出了這些更新,這些只是我認(rèn)為比較有趣的部分。用最新的 Java 版本來(lái)運(yùn)行大型項(xiàng)目需要很大的勇氣,如果是從 Java 8 遷移過(guò)來(lái),則更需要勇氣。


          如果有人猶豫不決,是可以理解的。但是,即使你沒(méi)有遷移計(jì)劃,或者某個(gè)升級(jí)計(jì)劃可能持續(xù)數(shù)年之久,跟上語(yǔ)言新特性的變化總歸是件好事。我希望我分享的這些內(nèi)容能夠讓它們更加深入人心,讓閱讀過(guò)這些內(nèi)容的人都可以開(kāi)始考慮如何使用它們!


          Java 17 很特別——它是下一個(gè)長(zhǎng)期支持版本,接過(guò)了 Java 11 的接力棒,并且很可能在未來(lái)幾年內(nèi)成為遷移最多的 Java 版本。即使你現(xiàn)在還沒(méi)有做好準(zhǔn)備,可以開(kāi)始學(xué)習(xí)起來(lái)了,當(dāng)你身處基于 Java 17 的項(xiàng)目當(dāng)中,你已經(jīng)是一名經(jīng)驗(yàn)豐富的開(kāi)發(fā)者!

          來(lái)源:infoq.com/articles/six-features-jdk12-to-jdk17/



          最近熬夜給大家準(zhǔn)備了非常全的一套Java一線大廠面試題。全面覆蓋BATJ等一線互聯(lián)網(wǎng)公司的面試題及解答,由BAT一線互聯(lián)網(wǎng)公司大牛帶你深度剖析面試題背后的原理,不僅授你以魚(yú),更授你以漁,為你面試掃除一切障礙。



          資源,怎么領(lǐng)取?


          掃二維碼,加我微信,備注:面試題


          一定要備注:面試題,不要急哦,工作忙完后就會(huì)通過(guò)!



          瀏覽 33
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久高清无码视频 | 国产精品久久毛片 | 亚洲成a人片77777精品 | 国产视频高清在线 | 78成人视频 |