在此之前,Java 的新版本很少出現,而且出現的時間也很延遲。現在,Oracle成功地保持了自己設定的「每六個月推出新 Java」的節奏。所以幾天前,嚴格按照計劃,我們終於收到了Java SE 11和JDK(Java 開發工具包) 的實作。與往常一樣,新版本將與舊版本相容,對 Java 11 的支援將不早於 2026 年 12 月結束。
Java SE 11 中的新功能(開發人員可見)
回想一下,在 Java 中,變更是透過實施 JEP「JDK 增強提案」而進行的。JEP是一項改進 OpenJDK 的提案,可能會被批准、延遲或拒絕。也就是說,本質上,JEP 的集合是 OpenJDK 的一種開發策略。在新「功能」之前的方括號中,我們將標明對應 JEP 的編號。 [323] Lambda 參數的局部變數語法- lambda 參數的 var 語法 Java 10 引入了 var 關鍵字,這使得可以不明確指定局部變數的類型。這簡化了程式碼。JEP 323透過 lambda 表達式擴展了此語法的使用。簡單的例子:list.stream ()
.map ((var s) -> s.toLowerCase ())
.collect (Collectors.toList ());
正如著名 Java 佈道者 Simon Ritter所寫,經驗豐富的 Java 程式設計師會注意到,在這種情況下使用 var 可能是不必要的,因為上面的程式碼可以替換為以下程式碼:
list.stream ()
.map (s -> s.toLowerCase ())
.collect (Collectors.toList ());
那為什麼要支援 var 呢?只有一種特殊情況 - 當您想要為 lambda 參數新增註解時。如果不涉及某種類型,這是不可能完成的,為了避免必須使用顯式類型,我們可以使用 var 來簡化一切,如下所示:
list.stream ()
.map ((@ Notnull var s) -> s.toLowerCase ())
.collect (Collectors.toList ());
[330] 啟動單一檔案原始程式碼程式 增強Java 啟動器以使用Java 原始程式碼將程式作為單一檔案啟動Java 經常因其冗長的語法和啟動(即使是一個簡單的應用程式)的多步驟「儀式」而受到批評。有時這會嚇跑新手。編寫一個僅列印「Hello World! 」的應用程式 ”,您需要編寫一個具有公共靜態void
main 方法的類別並使用System.out.println
. 完成此操作後,您必須使用javac編譯程式碼。最後,在此之後,您可以啟動應用程序,它將顯示不幸的問候語(當然,集成開發環境,無論是IDEA還是JavaRush內置的環境,都會自行執行這一“應用程序啟動魔法” - 編者註) 。老實說:在大多數程式語言中,執行程式的實際腳本看起來要簡單得多。JEP 330 無需編譯單文件應用程序,因此現在如果您使用命令列,只需鍵入
java HelloWorld.java
Java啟動器將偵測該檔案包含Java原始程式碼,並在執行前將程式碼編譯成類別檔案。您可以將參數放在原始碼檔案名稱之後或之前。執行應用程式時,放置在名稱後面的內容將作為參數傳遞。程式碼編譯後,名稱前面的內容將作為參數傳遞給 Java 啟動器。編譯器特定的選項(例如類別路徑)也將傳遞給javac進行編譯。 例子。線:
java -classpath / home / foo / java Hello.java Bonjour
將相當於這些行:
javac -classpath / home / foo / java Hello.java
java -classpath / home / foo / java Hello Bonjour
[321] HTTP 用戶端(標準) - HTTP 用戶端 API 支援已標準化。JDK 9 引入了新的API來支援HTTP 用戶端協定 (JEP 110)。由於 JDK 9 也引入了Java 平台模組系統 (JPMS),因此該 API 被作為孵化器模組包含在內(這些模組為開發人員提供尚未成為 Java SE 標準的新 API,而「即時」API 正在開發中)準備刪除- 開發人員可以嘗試新的API 並嘗試提供回饋)。一旦進行了必要的更改(該 API 已在 JDK 10 中更新),該 API 就可以成為標準的一部分。因此,HTTP Client API 現已正式包含在 Java SE 11 中。這為JDK引進了一個新的模組和套件java.net.http 。主要的新類型有: HttpClient HttpRequest HttpResponse WebSocket 此 API 可以同步或非同步使用。在非同步模式下,使用CompletionFutures
和CompletionStages
。 [320] 刪除 Java EE 和 CORBA 模組隨著Java 第九版中引入Java 平台模組系統 (JPMS) ,將整體rt.jar檔案拆分為多個模組成為可能。此外,JPMS 可讓您建立僅包含應用程式所需模組的 Java 執行時間環境,從而大大減少其大小。透過透明定義的模組邊界,可以更輕鬆地刪除 Java API 的過時部分 - 這就是 JEP 320 所做的。java.se.ee元模組包含六個模組,這些模組不會成為Java SE 11 標準的一部分,也不會包含在JDK中:
- 科爾巴
- 交易
- 啟用設定
- xml.綁定
- xml.ws
- xml.ws.註釋
新 API
由於將HTTP Client和Flight Recorder模組納入語言標準中,JDK 11 中出現了大量新 API 。完整的 API 清單請參考下面由 Gunnar Morling 編譯的不同版本 JDK 的綜合比較。在本說明中,我們將列出java.net.http、jdk.jfr和java.security模組中未包含的一些新方法。 java.lang.String 可以說是 JDK 11 API 中對 String 最重要的變更之一,有幾個有用的新方法。boolean isBlank ()
:如果字串為空或僅包含空格,則傳回 true,否則傳回 false。Stream lines()
:傳回從此字串中提取的行流,以行終止符分隔。String repeat (int)
:傳回一個字串,其值是該字串重複int次的串聯。String strip ()
:傳回一個字串,其中第一個非空格字元之前或之後刪除了所有空格。String stripLeading ()
:傳回刪除了第一個非空格字元之前的所有空格的字串。String stripTrainling ()
:傳回一個字串,其中刪除最後一個非空格字元後出現的所有空格。
strip()
該方法已經做了 類似的事情trim ()
,但是透過空間這些方法意味著不同的事情。在這種情況下,trim()
僅空格被截斷,並且 in strip()
- 也被截斷特殊字符,例如製表符。 java.lang.StringBuffer java.lang.StringBuilder 這兩個類別都包含一個compareTo ()
接受StringBuffer
/StringBuilder
並且回傳的新方法int
。詞法比較方法與新方法類似compareTo() CharSequence
。 java.io.ByteArrayOutputStream
void writeBytes (byte [])
:將參數的所有位元組寫入java.io.FileReader輸出流
Charset
. java.io.FileWriter 四個新的建構子允許您指定Charse
t。 java.io.InputStream
io.InputStream nullInputStream ()
:返回InputStream
,不讀取任何位元組。如何使用這個方法呢?您可以將其視為類似 /dev/null 的東西,以丟棄不需要的輸出,或者註入始終返回零位元組的輸入。
io.OutputStream nullOutputStream ()
io.Reader nullReader ()
io.Writer nullWriter ()
String toString (int)
:這是現有方法的重載,但使用 int 而不是 char。
int compare (CharSequence, CharSequence)
: 按字典順序比較兩個實例CharSequence
。如果第一個序列依字典順序小於、等於或大於第二個序列,則分別傳回負值、零或正值。
lang.Object clone ()
:Java 佈道者 Simon Ritter 承認這種方法讓他感到困惑。該類別
Reference
沒有實作接口
Cloneable
,並且該方法將始終拋出異常
CloneNotSupportedException
。不過,專家表示,這種方法將來會有用。
runFinalizersOnExit ()
已從這兩個類別中刪除,這可能會導致相容性問題。 java.lang.Thread 沒有其他方法,我們只會提到destroy ()
它們stop (Throwable)
已被刪除。然而stop ()
,不帶任何參數的 仍然可用。請記住這一點,因為可能存在相容性問題。 java.nio.ByteBuffer java.nio.CharBuffer java.nio.DoubleBuffer java.nio.FloatBuffer java.nio.LongBuffer java.nio.ShortBuffer 在所有這些類別中,語言開發人員添加了一個方法mismatch ()
,用於查找並返回該方法緩衝區與給定緩衝區之間的第一個不匹配。 java.nio.channels.SelectionKey
int interestOpsAnd (int)
int interestOpsOr (int)
int select (java.util.function.Consumer, long)
:選擇並在對應頻道已準備好進行 I/O 操作的按鍵上執行操作。long 參數是逾時。int select (java.util.function.Consumer)
:與上面的方法類似,但沒有超時。int selectNow (java.util.function.Consumer)
:與上面的方法類似,只是它是非阻塞的。
String readString (Path)
:將檔案中的所有內容讀取到字串中,使用UTF-8編碼將位元組解碼為字元。String readString (Path, Charset)
:與上面的方法類似,但使用 將位元組解碼為字元Charset
。Path writeString (Path, CharSequence, java.nio.file. OpenOption [])
:如果將字元序列寫入CharSequence
文件,這些字元將被編碼為位元組(使用UTF-8)。Path writeString (Path, CharSequence, java.nio.file. Charset, OpenOption [])
:與上面的方法類似,只是使用 將字元編碼為位元組Charset
。
- Path(String, String[]):返迴路徑,轉換路徑字串或組合形成路徑字串的字串序列。
- 路徑(net.URI):透過轉換URI返迴路徑。
Object [] toArray (java.util.function.IntFunction)
:傳回一個包含該集合中所有元素的數組,使用提供的生成器函數來分發傳回的數組。
void forEach (java.util.function.Consumer)
:對每個Iterable元素執行指定的操作,直到所有元素都已處理完畢或該操作引發異常。boolean removeAll (java.util.Collection)
:刪除該集合中也包含在指定集合中的所有元素(可選操作)。boolean removeIf (java.util.function.Predicate)
:刪除此集合中滿足給定謂詞的所有元素。boolean retainAll (java.util.Collection)
:僅保留此集合中包含在指定集合中的元素(可選操作)。
long convert (java.time.Duration)
:將給定的持續時間轉換為此單位。
Predicate not(Predicate)
:回傳一個謂詞,它是給定謂詞的否定。
lines.stream ()
.filter (s ->! s.isBlank ())
可以轉換成這樣:
lines.stream ()
.filter (Predicate.not (String :: ISBLANK))
如果我們使用靜態導入,那麼這就是我們得到的:
lines.stream ()
.filter (not(String :: ISBLANK))
java.util.Optional java.util.OptionalInt java.util.OptionalDouble java.util.OptionalLong
boolean isEmpty ()
:如果沒有值則回傳true ,否則回傳 false。
Predicate asMatchPredicate ()
:Java 專家 Simon Ritter 認為這裡可能隱藏著真正的 JDK 11 API gem。該方法創建一個謂詞來檢查該模式是否與給定的輸入字串相符。
int deflate (ByteBuffer)
:壓縮輸入資料並用壓縮資料填入指定緩衝區。int deflate (ByteBuffer, int)
:壓縮輸入資料並用壓縮資料填入指定緩衝區。傳回壓縮資料的實際量。void setDictionary (ByteBuffer)
:將給定字典設定為在給定緩衝區中壓縮為位元組。這是現有方法的重載,現在可以接受ByteBuffer
,而不是位元組數組。void setInput (ByteBuffer)
:設定要壓縮的輸入資料。它也是現有方法的重載。
int inflate (ByteBuffer)
:將位元組解壓縮到指定的緩衝區中。傳回未壓縮的實際位元組數。void setDictionary (ByteBuffer)
:將給定字典設定為給定緩衝區中的位元組。是現有方法的重載形式。void setInput (ByteBuffer)
:設定解壓縮的輸入資料。現有方法的重載形式。
void addAll (Collection)
:新增集合中存在的所有元素。void addAll (int, Collection)
:新增集合中存在的所有元素,從指定索引開始。
int [] getSelectedIndices ()
:按升序傳回所選模型中所有所選索引的陣列。int getSelectedItemsCount ()
:傳回所選項目的數量。
shell.JShellException getCause ()
:傳回此 EvalException 所呈現的執行客戶端中的可拋出原因,如果原因不存在或未知,則傳回 null。
Java 11 的非開發人員功能
[181]基於嵌套的存取控制 Java等語言透過內部類別支援嵌套類別。為此,編譯器必須執行某些技巧。例如:public class Outer {
private int outerInt;
class Inner {
public void printOuterInt() {
System.out.println("Outer int = " + outerInt);
}
}
}
編譯器會在編譯之前進行修改以產生類似以下內容的內容:
public class Outer {
private int outerInt;
public int access$000() {
return outerInt;
}
}
class Inner$Outer {
Outer outer;
public void printOuterInt() {
System.out.println("Outer int = " + outer.access$000());
}
}
儘管邏輯上內部類別與外部類別是同一程式碼的一部分,但它被編譯為單獨的類別。因此,此操作需要一個合成連接方法,該方法必須由編譯器創建,以提供對外部類別的私有欄位的存取。此 JEP 引入了巢的概念,其中同一巢的兩個成員(在我們的範例中為外部和內部)是築巢夥伴。為類別文件格式定義了兩個新屬性:NestHost和NestMembers。這些變更對於支援巢狀類別和字節碼的其他語言很有用。此函數為java.lang.Class引入了三個新方法: Class getNestHost () Class [] getNestMembers () boolean isNestmateOf (Class) [309] 動態類別檔案常數 此JEP 描述了類別檔案格式的擴展,以支援新的類別檔案格式持久池形式為CONSTANT_Dynamic。動態常數的想法似乎是矛盾的,但本質上你可以將其視為 Java 11 中的最終值。池常數的值不是在編譯時設定的(與其他常數不同),而是使用引導程式確定提前期價值的方法。因此該值是動態的,但由於其值僅設定一次,因此它也是恆定的。此功能主要針對開發新語言和編譯器的人們,這些語言和編譯器將產生字節碼和類別檔案作為輸出以在 JVM 上運行。 [315] 改進 Aarch64 Intrinsics 此 JEP 由 Red Hat 社群提出。JVM 現在可以使用 Arm 64 指令集中提供的更多專用指令。特別是,這提高了 、 方法sin ()
和cos ()
java.lang.Mathlog ()
類別的效能。 [318] Epsilon:無操作垃圾收集器 與JEP 315一樣,您可以感謝 Red Hat 引入了 Epsilon 垃圾收集器。Epsilon 的不同尋常之處在於它實際上並沒有收集垃圾!建立新物件時,它會根據需要分配內存,但不會回收未註冊物件佔用的空間。“重點是什麼?“, - 你問。事實證明,這個「垃圾收集」有兩個用途:
- 首先,該垃圾收集器旨在確保新的 GC 演算法根據其效能影響進行評估。這個想法是使用 Epsilon 運行範例應用程式並產生一組指標。啟用新的垃圾收集演算法,執行相同的測試,然後比較結果。
- 對於非常短的任務(想想雲端中的無伺服器函數),您可以保證不會超出分配給堆的記憶體。這可以透過消除應用程式程式碼中的開銷(包括收集決定是否運行收集器所需的統計資料)來提高效能。如果堆空間耗盡,JVM 可能會透過以下三種方式之一配置錯誤:
- 正常的稱為
OutOfMemoryError
. - 執行堆疊重置
- JVM 硬碟發生故障,並且可能正在執行其他任務(例如啟動偵錯器)。
- 正常的稱為
- 提供用於將資料作為事件生成和使用的 API
- 提供緩衝機制和二進位資料格式
- 允許自訂和過濾事件
- 為作業系統、JVM HotSpot 和 JDK 庫提供事件
GO TO FULL VERSION