Java 21 是 Java 17 之后的下一個(gè) LTS 版本。虛擬線程在 Java 21 中將成為正式功能。可以預(yù)期的是,Java 21 會(huì)成為一個(gè)很流行的 Java 版本。
Java 21 將在 2023 年 9 月 19 日發(fā)布。目前 Java 21 包含的內(nèi)容已經(jīng)基本確定了。下面來(lái)梳理一下 Java 21 中會(huì)包含的內(nèi)容。
正式功能
虛擬線程 (Virtual Threads)
自從 Java 19 中引入之后,虛擬線程已經(jīng)成為了 Java 社區(qū)中火熱的話題。虛擬線程會(huì)改變 Java 的多線程編程。虛擬線程會(huì)成為 Java 21 的殺手锏功能,促使更多用戶升級(jí)到 Java 21。
順序集合(Sequenced Collections)
順序集合中的元素有確定的出現(xiàn)順序(encounter order)。Java 21 新增了與順序集合相關(guān)的接口,統(tǒng)一了與順序集合相關(guān)的操作,包括獲取第一個(gè)和最后一個(gè)元素,在集合的頭部和尾部插入和刪除元素,以及逆序遍歷集合等。
新增的順序集合相關(guān)的接口包括?SequencedCollection
、SequencedSet
?和?SequencedMap
。Java 集合框架中的已有類也進(jìn)行了調(diào)整。更新之后的集合框架的類結(jié)構(gòu)如下圖所示。
記錄類型的模式(Record Patterns)
記錄類型的模式可以解構(gòu)記錄對(duì)象中的值,可以方便地提取記錄中的組件。
比如下面的記錄類型?Point
:
record Point(int x, int y) {}
通過(guò)下面的方式就可以解構(gòu)出?Point
?中的組件?x
?和?y
。
static void printSum(Object obj) {
if (obj instanceof Point(int x, int y)) {
System.out.println(x + y);
}
}
switch 的模式匹配(Pattern Matching for switch)
增強(qiáng) Java 中的 switch 表達(dá)式和語(yǔ)句,允許在 case 標(biāo)簽中使用模式。當(dāng)模式匹配時(shí),執(zhí)行 case 標(biāo)簽對(duì)應(yīng)的代碼。
在下面的代碼中,switch 表達(dá)式使用了類型模式來(lái)進(jìn)行匹配。
static String formatterPatternSwitch(Object obj) {
return switch (obj) {
case Integer i -> String.format("int %d", i);
case Long l -> String.format("long %d", l);
case Double d -> String.format("double %f", d);
case String s -> String.format("String %s", s);
default -> obj.toString();
};
}
分代式 ZGC (Generational ZGC)
增強(qiáng) Z 垃圾回收器(ZGC)來(lái)支持不同的世代。年輕和年老的對(duì)象分別存放在不同的世代中,使得年輕的對(duì)象可以更加頻繁的被回收。
廢棄 Windows 32 位版本(Deprecate the Windows 32-bit x86 Port for Removal)
廢棄 Windows 32 位 x86 版本,將在以后的 OpenJDK 版本中刪除。之所以廢棄 Windows 32位 x86 版本, 主要有幾個(gè)動(dòng)機(jī):
Windows 10,支持 32 位的最后一個(gè) Windows 操作系統(tǒng),將在2025年10月終止。結(jié)束對(duì) Windows 32位 x86 版本的支持,可以把精力轉(zhuǎn)移到更加重要的事情上。
另外一個(gè)原因是,虛擬線程在 Windows 32 位 x86 版本的實(shí)現(xiàn)回退到了使用內(nèi)核線程,沒(méi)辦法享受到 Loom 項(xiàng)目帶來(lái)的好處。
預(yù)覽功能
未命名類和實(shí)例 main 方法 (Unnamed Classes and Instance Main Methods)
該 JEP 的目標(biāo)是簡(jiǎn)化 Java 的入口類。一直以來(lái),Java 的入口類的?main
?方法的聲明有著很嚴(yán)格的要求,必須是?public static void main(String[] args)
。對(duì)于 Java 初學(xué)者來(lái)說(shuō),這個(gè)?main
?方法的聲明引入了太多的 Java 語(yǔ)法概念,不利于初學(xué)者快速上手。
在經(jīng)過(guò)簡(jiǎn)化之后,不再對(duì)?main
?方法的聲明進(jìn)行嚴(yán)格的限制,而是允許多種聲明方式。具體來(lái)說(shuō), 在啟動(dòng)的入口類中會(huì)按照如下順序依次查找?main
?方法:
首先是?
public static void main(String[] args)
?方法,其次是聲明為 protected 或 package 的?
static void main(String[] args)
?方法,接著是非私有的?
static void main()
?方法,然后是非私有的實(shí)例方法?
void main(String[] args)
,最后是非私有的實(shí)例方法?
void main()
。
對(duì)于后面兩種情況,由于調(diào)用的是實(shí)例方法,需要有入口類的實(shí)例。這就要求入口類有一個(gè)非私有的,不帶任何參數(shù)的構(gòu)造方法。在啟動(dòng)時(shí),首先創(chuàng)建出入口類的對(duì)象,再調(diào)用對(duì)象的?main
?方法。
未命名類允許省略外層的 Java 類聲明,直接把?main
?方法作為頂層元素,寫在 Java 源代碼文件中。main
?方法所依賴的其他方法和字段,也同樣作為頂層元素。Java 編譯器會(huì)自動(dòng)生成一個(gè)匿名類,并調(diào)用其中的?main
?方法。
在對(duì)入口類進(jìn)行簡(jiǎn)化之后,只需要下面的代碼就可以了。
void main() {
System.out.println("Hello, World!");
}
字符串模板 (String Templates)
字符串模板是 Java 一直以來(lái)缺少的功能。Java 21 的字符串模板是一個(gè)通用的實(shí)現(xiàn),可以把任何字符串轉(zhuǎn)換成任意類型的對(duì)象。
字符串模板的實(shí)現(xiàn)由兩個(gè)部分組成,分別是?StringTemplate
?表示的模板,以及?StringTemplate.Processor
?表示的模板處理器。StringTemplate
?表示的模板中包含需要求值的表達(dá)式,如?\{name}
?表示獲取?name
?的值。
Java 內(nèi)置提供了幾個(gè)模板處理器的實(shí)現(xiàn)。STR
?用來(lái)對(duì)包含表達(dá)式的字符串模板進(jìn)行求值。這是通常意義上的字符串模板的用法。
int x = 10, y = 20;
String s = STR."\{x} + \{y} = \{x + y}";
FMT
?可以進(jìn)行格式化,使用的是?java.util.Formatter
?支持的語(yǔ)法。
record Rectangle(String name, double width, double height) {
double area() {
return width * height;
}
}
Rectangle[] zone = new Rectangle[] {
new Rectangle("Alfa", 17.8, 31.4),
new Rectangle("Bravo", 9.6, 12.4),
new Rectangle("Charlie", 7.1, 11.23),
};
String table = FMT."""
Description Width Height Area
%-12s\{zone[0].name} %7.2f\{zone[0].width} %7.2f\{zone[0].height} %7.2f\{zone[0].area()}
%-12s\{zone[1].name} %7.2f\{zone[1].width} %7.2f\{zone[1].height} %7.2f\{zone[1].area()}
%-12s\{zone[2].name} %7.2f\{zone[2].width} %7.2f\{zone[2].height} %7.2f\{zone[2].area()}
\{" ".repeat(28)} Total %7.2f\{zone[0].area() + zone[1].area() + zone[2].area()}
""";
RAW
?生成一個(gè)不對(duì)字符串做任何處理的?StringTemplate
?對(duì)象。
可以創(chuàng)建自定義的字符串模板處理器來(lái)生成非?String
?類型的對(duì)象。下面代碼中的?JSON
?從字符串模板中生成?JSONObject
?對(duì)象。
var JSON = StringTemplate.Processor.of(
(StringTemplate st) -> new JSONObject(st.interpolate())
);
未命名模式和變量 (Unnamed Patterns and Variables)
下劃線終于來(lái)了??梢允褂孟聞澗€表示未命名的變量,以及模式匹配時(shí)不使用的組件。
未命名變量的典型場(chǎng)景是?try-with-resources
?語(yǔ)句和?catch
?子句中的異常變量。
try (var _ = ScopedContext.acquire()) {
}
try { ... }
catch (Exception _) { ... }
catch (Throwable _) { ... }
未命名模式是一個(gè)無(wú)條件的模式,并不綁定任何值。未命名模式變量出現(xiàn)在類型模式中。
if (r instanceof ColoredPoint(_, Color c)) { ... c ... }
switch (b) {
case Box(RedBall _), Box(BlueBall _) -> processBox(b);
case Box(GreenBall _) -> stopProcessing();
case Box(_) -> pickAnotherBox();
}
外部方法和內(nèi)存 API (Foreign Function & Memory API)
外部方法和內(nèi)存 API提供了一種新的方式來(lái)與 Java 運(yùn)行時(shí)之外的代碼和數(shù)據(jù)來(lái)進(jìn)行互操作。該 API 可以高效調(diào)用外部方法,并安全訪問(wèn)外部?jī)?nèi)存。該 API 用來(lái)替代 JNI。
Java 21 中是該 API 的第 3 個(gè)預(yù)覽版。
孵化功能
矢量 API (Vector API)
Vector API 是 OpenJDK 中 Panama 項(xiàng)目的一部分。Vector API 的作用是描述矢量計(jì)算,并在運(yùn)行時(shí)編譯成 CPU 架構(gòu)上的矢量計(jì)算指令。
矢量是一組標(biāo)量值的序列。標(biāo)量值的數(shù)量取決于硬件定義的 vector lane 的數(shù)量。在對(duì)兩個(gè)矢量進(jìn)行計(jì)算時(shí),會(huì)在每條 lane 上對(duì)兩個(gè)矢量相應(yīng)的標(biāo)量值進(jìn)行計(jì)算。通過(guò)并行計(jì)算,兩個(gè)矢量計(jì)算的速度與單個(gè)標(biāo)量值的計(jì)算速度是相同的,極大地提高了計(jì)算速度。這被稱為 SIMD(Single Instruction Multiple Data),單指令多數(shù)據(jù)。
HotSpot 虛擬機(jī)已經(jīng)支持自動(dòng)的矢量化,但是存在很大的局限性,開發(fā)人員難以有效的利用。Vector API 提供了一種方式來(lái)編寫復(fù)雜的矢量算法。雖然底層仍然使用的是 HotSpot 的自動(dòng)矢量化,但是矢量化的結(jié)果更加可靠。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-724064.html
試驗(yàn)功能
分代式 Shenandoah(Generational Shenandoah)
為垃圾回收器 Shenandoah 增加了分代式支持。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-724064.html
到了這里,關(guān)于Java 21 新特性和改進(jìn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!