Java程式設計師必須知道的Java11特性

語言: CN / TW / HK

小知識,大挑戰!本文正在參與“     程式設計師必備小知識     ”創作活動

本文同時參與 「掘力星計劃」     ,贏取創作大禮包,挑戰創作激勵金

Java 11是自Java 8以來的又一個LTS版本,是目前全球使用最多的LTS版本之一。今天我們接著在Java 9 到 Java 17系列文章中來認識針對普通開發者的Java 11。

字串API增強

在Java 11中,針對String的操作進一步得到加強。避免我們在很常見的場景中引入額外的、複雜的API。

isBlank()

用來判斷字串是不是空字元""或者trim()之後(" ")為空字元:

java  String blankStr = "   ";  // true  boolean trueVal = blankStr.isBlank();

lines()

將一個字串按照行終止符(換行符\n或者回車符\r)進行分割,並將分割為Stream流:

java          String newStr = "Hello Java 11 \n felord.cn \r 2021-09-28";  ​          Stream<String> lines = newStr.lines();          lines.forEach(System.out::println);  //       Hello Java 11  //       felord.cn  //       2021-09-28

strip()

去除字串前後的“全形和半形”空白字元:

java  String str = "HELLO\u3000";  // str = 6  System.out.println("str = " + str.length());  // trim = 6  System.out.println("trim = " + str.trim().length());  // strip = 5  System.out.println("strip = " + str.strip().length());

這不由得想起來trim()方法,從上面也看出來了差別,trim()只能去除半形空白符。

strip()方法還有兩個變種,stripLeading()用來去除前面的全形半形空白符;stripTrailing()用來去除尾部的全形半形空白符。

repeat(n)

按照給定的次數重複串聯字串的內容:

java  String str = "HELLO";  // 空字元  String empty = str.repeat(0);  // HELLO  String repeatOne = str.repeat(1);  // HELLOHELLO  String repeatTwo = str.repeat(2);

集合轉對應型別的陣列

之前想集合轉對應的陣列很麻煩,要麼用迭代;要麼用Stream流,現在你可以這樣:

java          List<String> sampleList = Arrays.asList("felord.cn", "java 11");          // array = {"felord.cn", "java 11"};          String[] array = sampleList.toArray(String[]::new);

斷言取反

java.util.function.Predicate<T>是我們很常用的斷言謂詞函式。在以前取反我們得藉助於!符號,到了Java 11我們可以藉助於其靜態方法not來實現,這樣語義就更加清晰了:

java          List<String> sampleList = Arrays.asList("felord.cn", "java 11","jack");          // [jack]          List<String> result = sampleList.stream()                  // 過濾以j開頭的字串                 .filter(s -> s.startsWith("j"))                  // 同時不包含11的字串                 .filter(Predicate.not(s -> s.contains("11")))                 .collect(Collectors.toList());

其實Predicate<T>在最初版本還提供了一個取反的預設方法:

default Predicate<T> negate() {          return (t) -> !test(t);     }

這個我在往期文章中也使用過它來做組合校驗,這兩個方法的場景是不一樣的。

var可以用於修飾Lambda區域性變數

在Java 10中引入的var來進行型別推斷。在Java 10中它不能用於修飾Lambda表示式的入參,其實對於一個Lambda表示式來說它入參的型別其實是可以根據上下文推斷出來的。拿上面的例子來說,s -> s.startsWith("j")中的s肯定是字串型別,因此在Java 11中var可以用於修飾Lambda區域性變數:

java          List<String> result = sampleList.stream()                  // 過濾以j開頭的字串                 .filter((@NotNull var s) -> s.startsWith("j"))                  // 同時不包含11的字串                 .filter(Predicate.not((@NotNull var s) -> s.contains("11")))                 .collect(Collectors.toList());

如果我們不宣告var就沒有辦法為輸入引數新增@NotNull註解。

檔案中讀寫字串內容更方便

Java 11中可以更輕鬆地從檔案中讀取和寫入字串內容了,我們可以通過Files工具類提供的新的靜態方法readStringwriteString分別進行讀寫檔案的字串內容,放在之前老麻煩了,特別是對IO流不熟悉的同學來說。現在簡單幾行就搞定了:

java String dir= "C://yourDir"; // 寫入檔案 Path path = Files.writeString(Files.createTempFile(dir, "hello", ".txt"), "hello java 11"); // 讀取檔案 String fileContent = Files.readString(path);

巢狀類的訪問控制規則

在Java 11之前,內部巢狀類訪問外部類的私有屬性和方法是可行的:

```java public class Outer { private int outerInt;

 class Inner {
   public void printOuterField() {
     System.out.println("Outer field = " + outerInt);
   }
}

} ```

但是如果你通過反射API實現內部類訪問外部類的私有屬性和方法就會丟擲IllegalStateException異常。Java 11 修復了反射不能訪問的問題.

JVM 訪問規則不允許巢狀類之間進行私有訪問。我們能通過常規方式可以訪問是因為 JVM 在編譯時為我們隱式地建立了橋接方法。Java 11 中引入了兩個新的屬性:一個叫做 NestMembers 的屬性,用於標識其它已知的靜態 nest 成員;另外一個是每個 nest 成員都包含的 NestHost 屬性,用於標識出它的 nest 宿主類。在編譯期就映射了雙方的寄宿關係,不再需要橋接了。

HttpClient支援HTTP2

HttpClient到了Java 11後開始支援HTTP2,底層進行了大幅度的優化,並且現在完全支援非同步非阻塞。

HttpClient 的包名由 jdk.incubator.http 改為 java.net.http

其它

Java 11 中,還有一些其它方面的特性和優化,比如引入了ZGC,支援支援 TLS 1.3 協議,引入了動態呼叫(invokedynamic)機制,另外原來商業版的JFR也進行了開源整合等等。在年初的Java生態調查資料顯示Java 11的使用者數量大幅增長,成為了主流版本選擇之一。

下方留言,掘金官方送周邊啦 ~~博文中哪裡寫的不好的歡迎評論區指出~~ 掘金官方抽送100個周邊啦