Java 9 - 17 特性解讀:Java 11

Java 11是自Java 8以來的又一個(gè)LTS版本,是目前全球使用最多的LTS版本之一。今天我們接著在Java 9 到 Java 17系列文章中來認(rèn)識(shí)針對(duì)普通開發(fā)者的Java 11。
字符串API增強(qiáng)
在Java 11中,針對(duì)String的操作進(jìn)一步得到加強(qiáng)。避免我們?cè)诤艹R姷膱?chǎng)景中引入額外的、復(fù)雜的API。
isBlank()
用來判斷字符串是不是空字符""或者trim()之后(" ")為空字符:
String blankStr = " ";
// true
boolean trueVal = blankStr.isBlank();
lines()
將一個(gè)字符串按照行終止符(換行符\n或者回車符\r)進(jìn)行分割,并將分割為Stream流:
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()
去除字符串前后的“全角和半角”空白字符:
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()方法還有兩個(gè)變種,stripLeading()用來去除前面的全角半角空白符;stripTrailing()用來去除尾部的全角半角空白符。
repeat(n)
按照給定的次數(shù)重復(fù)串聯(lián)字符串的內(nèi)容:
String str = "HELLO";
// 空字符
String empty = str.repeat(0);
// HELLO
String repeatOne = str.repeat(1);
// HELLOHELLO
String repeatTwo = str.repeat(2);
集合轉(zhuǎn)對(duì)應(yīng)類型的數(shù)組
之前想集合轉(zhuǎn)對(duì)應(yīng)的數(shù)組很麻煩,要么用迭代;要么用Stream流,現(xiàn)在你可以這樣:
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>是我們很常用的斷言謂詞函數(shù)。在以前取反我們得借助于!符號(hào),到了Java 11我們可以借助于其靜態(tài)方法not來實(shí)現(xiàn),這樣語義就更加清晰了:
List<String> sampleList = Arrays.asList("felord.cn", "java 11","jack");
// [jack]
List<String> result = sampleList.stream()
// 過濾以j開頭的字符串
.filter(s -> s.startsWith("j"))
// 同時(shí)不包含11的字符串
.filter(Predicate.not(s -> s.contains("11")))
.collect(Collectors.toList());
其實(shí)Predicate<T>在最初版本還提供了一個(gè)取反的默認(rèn)方法:
default Predicate<T> negate() {
return (t) -> !test(t);
}
這個(gè)我在往期文章中也使用過它來做組合校驗(yàn),這兩個(gè)方法的場(chǎng)景是不一樣的。
var可以用于修飾Lambda局部變量
在Java 10中引入的var來進(jìn)行類型推斷。在Java 10中它不能用于修飾Lambda表達(dá)式的入?yún)ⅲ鋵?shí)對(duì)于一個(gè)Lambda表達(dá)式來說它入?yún)⒌念愋推鋵?shí)是可以根據(jù)上下文推斷出來的。拿上面的例子來說,s -> s.startsWith("j")中的s肯定是字符串類型,因此在Java 11中var可以用于修飾Lambda局部變量:
List<String> result = sampleList.stream()
// 過濾以j開頭的字符串
.filter((@NotNull var s) -> s.startsWith("j"))
// 同時(shí)不包含11的字符串
.filter(Predicate.not((@NotNull var s) -> s.contains("11")))
.collect(Collectors.toList());
?如果我們不聲明
var就沒有辦法為輸入?yún)?shù)添加@NotNull注解。
文件中讀寫字符串內(nèi)容更方便
Java 11中可以更輕松地從文件中讀取和寫入字符串內(nèi)容了,我們可以通過Files工具類提供的新的靜態(tài)方法readString和writeString分別進(jìn)行讀寫文件的字符串內(nèi)容,放在之前老麻煩了,特別是對(duì)IO流不熟悉的同學(xué)來說。現(xiàn)在簡單幾行就搞定了:
String dir= "C://yourDir";
// 寫入文件
Path path = Files.writeString(Files.createTempFile(dir, "hello", ".txt"), "hello java 11");
// 讀取文件
String fileContent = Files.readString(path);
嵌套類的訪問控制規(guī)則
在Java 11之前,內(nèi)部嵌套類訪問外部類的私有屬性和方法是可行的:
public class Outer {
private int outerInt;
class Inner {
public void printOuterField() {
System.out.println("Outer field = " + outerInt);
}
}
}
但是如果你通過反射API實(shí)現(xiàn)內(nèi)部類訪問外部類的私有屬性和方法就會(huì)拋出IllegalStateException異常。Java 11 修復(fù)了反射不能訪問的問題.
?JVM 訪問規(guī)則不允許嵌套類之間進(jìn)行私有訪問。我們能通過常規(guī)方式可以訪問是因?yàn)?JVM 在編譯時(shí)為我們隱式地創(chuàng)建了橋接方法。Java 11 中引入了兩個(gè)新的屬性:一個(gè)叫做
NestMembers的屬性,用于標(biāo)識(shí)其它已知的靜態(tài) nest 成員;另外一個(gè)是每個(gè) nest 成員都包含的NestHost屬性,用于標(biāo)識(shí)出它的 nest 宿主類。在編譯期就映射了雙方的寄宿關(guān)系,不再需要橋接了。
HttpClient支持HTTP2
HttpClient到了Java 11后開始支持HTTP2,底層進(jìn)行了大幅度的優(yōu)化,并且現(xiàn)在完全支持異步非阻塞。
?
HttpClient的包名由jdk.incubator.http改為java.net.http。
其它
Java 11 中,還有一些其它方面的特性和優(yōu)化,比如引入了ZGC,支持支持 TLS 1.3 協(xié)議,引入了動(dòng)態(tài)調(diào)用(invokedynamic)機(jī)制,另外原來商業(yè)版的JFR也進(jìn)行了開源集成等等。在年初的Java生態(tài)調(diào)查數(shù)據(jù)顯示Java 11的用戶數(shù)量大幅增長,成為了主流版本選擇之一。
往期推薦
技術(shù)交流群
最近有很多人問,有沒有讀者交流群,想知道怎么加入。加入方式很簡單,有興趣的同學(xué),只需要點(diǎn)擊下方卡片,回復(fù)“加群“,即可免費(fèi)加入我們的高質(zhì)量技術(shù)交流群!
點(diǎn)擊閱讀原文,送你免費(fèi)Spring Boot教程!
