我們已經習慣了每六個月就會出現一個新的 JDK 版本。到目前為止,這種做法已經證明了自己的合理性,一些開發者擔心自己跟不上更新的擔憂是徒勞的:六個月的變化很少,而且不像以前那樣具有全球性。嗯,新手程式設計師可能根本沒有註意到這項創新。 然而,未來的軟體開發人員最好能夠跟上創新的步伐。在本文中,我們將按照傳統方式描述已接受的擴展提案 (JEP)。Java 13 僅包含 5 個 JEP 和 76 個新的核心庫元素(其中幾乎一半是 java.io 套件的簡單添加)。
JEP 355:文字區塊(預覽)
讓我們從更改語言的語法開始。其中最重要的是文字區塊。它們允許您避免轉義字元並了解如何格式化字串。您可能還記得JDK 12 不包含用於處理字串文字的預期原始字串文字 (JEP 326) 功能。在 Java 13 中,它被 JEP 355 及其文字區塊取代。您可能還記得,在 Java 中,字串用雙引號括起來。這很好,但問題是一行不能佔用原始檔案的多行(為了避免與 Java 行混淆,這裡我們將檔案行稱為「行」)。好吧,讓我們來看看,例如,\n
如果需要中斷,或連接多行表達式,則使用符號。結果不太好!嵌入 HTML、XML、SQL 或 JSON 片段的文字文字尤其麻煩。所有這些轉義、串聯和手動編輯使程式碼編寫起來不方便且難以閱讀。文字塊試圖解決這個問題。它們以呃...開頭並以三個雙引號結尾(我知道,這聽起來不太好)。引號之間的所有內容都被解釋為行的一部分,包括換行符。文字區塊的使用方式與標準文字文字完全相同,Java 將以相同的方式編譯程式碼。起始引號後面必須跟有行分隔符號;文字區塊不能在一行中使用,因此程式碼
String smallBlock = """Only one line""";
會導致以下錯誤:
TextBlock.java:3: error: illegal text block open delimiter sequence, missing line terminator
String smallBlock = """Text Block""";
^
TextBlock.java:3: error: illegal text block open delimiter sequence, missing line terminator
String smallBlock = """Text Block""";
^
現在可以像這樣寫一個簡單的 HTML 片段:
String htmlBlock = """
<html>
<body>
<p>CodeGym Web page</p>
</body>
<html>
""";
讓我們提一下使用文字區塊時最好注意的一些微妙之處。事實證明,結束引號的位置很重要:它決定如何處理偶爾出現的空白。在上面的範例中,結束引號與 HTML 文字的縮排對齊。在這種情況下,編譯器將刪除縮排空格,結果我們將得到如下行:
<html>
<body>
<p>My web page</p>
</body>
</html>
筆記:這樣的行將在行尾包含換行符號。如果不需要,可以將右引號「」」直接放在</html>標籤之後。如果我們將收盤價移近左邊距,這將改變刪除的縮排量。如果我們將它們向左移動兩個空格,我們就會為每行添加兩個空格以進行縮排。移動到左邊緣將導致保留所有填充。將引號進一步向右移動將不會產生任何效果,並且不會添加任何更多縮排。文字區塊作為預覽功能包含在 JDK 13 中。這意味著它們尚未包含在相應的 Java 語言規範中。也就是說,目前尚不清楚該功能是否會成為該語言的永久組成部分,或者只是這裡的一個客人。目前,開發人員可以測試該功能並發表意見。文字區塊的命運將取決於它:該功能可以改進,如果您不喜歡它,則可以將其完全刪除。如果您想在實作中嘗試文字區塊,請記住必須明確包含預覽功能才能編譯和執行。彙編:
javac --enable-preview --release 13 TextBlock.java
要運行該應用程序,您需要啟用預覽功能:
java --enable-preview TextBlock
該類別String
具有三個新方法來補充此語言變更:
formatted()
:使用字串本身作為格式字串來格式化字串。相當於挑戰format(this, args)
stripIndent()
:從字串中刪除隨機空格。如果您正在讀取多行字串並希望套用與明確聲明相同的空白排除,則這非常有用。translateEscapes()
:傳回帶有轉義序列(例如\ r
)的字串,並轉換為適當的 Unicode 值。
@PreviewFeature
會有助於解決這種情況,但它尚未包含在 JDK 中(儘管它很可能會出現在 JDK 14 中)。
JEP 354:開關表達式(預覽)
Java 12 引入了使用 switch 語句編寫表達式的新形式的提案 - JEP 325。事實證明,這是第一個預覽功能,它的命運證明向用戶提交提案是一個好主意。在 JDK 12 之前,switch
它只能用作執行操作但不傳回結果的語句。但在 Java 12 中,它允許將其用作switch
傳回可指派給變數的結果的表達式。中 case 語句的語法還有其他變更switch
。讓我們看一下 JEP 中的範例來了解其工作原理。
int numberOfLetters;
switch(dayOfWeek) {
case MONDAY:
case FRIDAY:
case SUNDAY:
numberOfLetter = 6;
break;
case TUESDAY
numberOfLetter = 7;
break;
case THURSDAY
case SATURDAY
numberOfLetter = 8;
break;
case WEDNESDAY
numberOfLetter = 9;
break;
default:
throw new IllegalStateException("Huh?: " + day);
}
在這個例子中,我們使用 valuedayOfWeek
將值賦給numberOfLetters
。由於操作人員工作的特殊性switch
,這段程式碼並不是最漂亮的,而且很容易出錯。首先,如果我們忘記將語句套用到break
每組案例標籤,我們將預設使用下一組案例標籤。這可能會導致難以發現的錯誤。其次,我們必須定義每組案例標籤。如果我們忘記了,那麼我們當然會得到一個編譯器錯誤,但這個選項也不是理想的。我們的程式碼也非常冗長,因為每個值都dayOfWeek
必須有自己的 case 標籤。使用新語法,我們可以獲得更清晰且不易出錯的程式碼:
int numberOfLetters = switch (dayOfWeek) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
default -> throw new IllegalStateException("Huh?: " + day);
};
現在我們只需要進行一次賦值(從表達式的傳回switch
值),並且可以使用逗號分隔的清單作為 case 標籤。而且,由於我們不使用運算符break
,因此我們消除了與之相關的問題。表達式語法switch
允許我們使用舊式語法,因此在 JDK 12 中我們可以這樣寫:
int numberOfLetters = switch (dayOfWeek) {
case MONDAY:
case FRIDAY:
case SUNDAY:
break 6;
case TUESDAY
break 7;
case THURSDAY
case SATURDAY
break 8;
case WEDNESDAY
break 9;
default:
throw new IllegalStateException("Huh?: " + day);
};
根據 Java 社群的說法,使用重載break
來指定傳回值可能會令人困惑。Java 語言還允許您將break
(and continue
) 與標籤一起使用,例如無條件跳躍運算子goto
。JEP 354 改變了這種用法break
,因此在 Java 13 中我們的程式碼略有變化:
int numberOfLetters = switch (dayOfWeek) {
case MONDAY:
case FRIDAY:
case SUNDAY:
yield 6;
case TUESDAY
yield 7;
case THURSDAY
case SATURDAY
yield 8;
case WEDNESDAY
yield 9;
default:
throw new IllegalStateException("Huh?: " + day);
};
接下來的三個 JEP 與 Java 虛擬機器相關。
JEP 350動態 CDS 存檔
此擴充功能可讓您在 Java 應用程式執行結束時動態歸檔類別。CDS 或類別資料共用可讓您將啟動時啟動的所有類別打包到一個特殊的檔案中class data sharing
,預設使用這些相同類別的清單。這會顯著加快應用程式的啟動速度並節省 RAM。先前,使用 AppCDS 是一個多步驟過程,涉及建立相關類別的清單並使用該清單建立用於後續運行的存檔。現在所需要做的就是使用 -XX: 標誌啟動應用程序,ArchiveClassesAtExit
指示將寫入存檔的位置。透過這種方法,應用程式正常停止後,類別會自動打包到存檔中。
JEP 351 ZGC:取消提交未使用的內存
一年前,JDK 11引進了 ZGC,這是一種實驗性、可擴展、低延遲的垃圾收集器。起初,ZGC 的行為相當奇怪:它不允許將記憶體傳回給作業系統,即使不再需要它。對於某些環境,例如容器,資源同時被多個服務使用,這可能會限制系統的可擴展性和效率。ZGC 堆由所謂的 ZPage 組成。當 ZPage 在垃圾收集週期期間被清除時,它們將返回 ZPageCache。此快取中的 ZPage 按最近使用的時間排序。在Java 13中,ZGC會將被辨識為長時間未使用的頁面傳回給作業系統。這樣它們就可以被其他行程重複使用。JEP 353重新實作舊版 Socket API
兩個 API 實作仍然java.net.Socket
是JDK 1.0。java.net.ServerSocket
在此以及所有後續 JDK 中,這些 API 的實作使用了多種技術(例如使用執行緒堆疊作為 I/O 緩衝區),這使得它們不靈活且難以維護。為了解決這個問題,JDK 13中提供了新的實作NioSocketImpl
。它不再需要本機程式碼,從而更容易移植到不同的平台。該類別還使用現有的緩衝區高速緩存機制(避免為此目的使用線程堆疊)和鎖定java.util.concurrent
而不是同步方法。這將簡化與Project Loom光纖的整合。
新 API
我們之前提到,Java 13 在基底類別庫中包含 76 個新 API。它們涵蓋以下領域:- Unicode 支援更新。
String
三種支援文字區塊的新方法(請參閱上面的 JEP 255 描述)。- 類別
java.nio
現在具有絕對(而不是相對)get
和設定方法。它們與抽象基底類別一樣,包含用於檢索部分緩衝區的 Buffer
方法。slice()
force()
此類別方法MappedByteBuffer
強制將緩衝區部分寫入其後備儲存。nio.FileSystem
新增了三個新的重載形式,newFileSystem()
用於存取作為檔案系統的檔案內容。- 一種新的有趣的方法出現
javax.annotation.processing.ProcessingEnvironment
了。isPreviewEnabled()
。它會告訴您是否啟用了預覽功能。這很有趣,因為上面提到的註釋@PreviewFeature
要等到 JDK 14 發布後才可用。 DocumentBuilderFactory
並SAXParserFactory
獲得javax.xml.parsers
三種用於創建命名空間感知實例的新方法。
GO TO FULL VERSION