Java Development Kit (JDK) 21作為Oracle長期支持(LTS)版本,于2023年9月正式發布,帶來了多項令人振奮的新特性和改進。本文將全面介紹JDK 21中的主要更新,幫助開發者了解如何利用這些新功能提升開發效率和代碼質量。
一、虛擬線程(Virtual Threads)正式發布
虛擬線程是JDK 21中最引人注目的特性之一,它從預覽階段(JDK 19和20)正式轉正。
// 創建虛擬線程的簡單示例
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {IntStream.range(0, 10_000).forEach(i -> {executor.submit(() -> {Thread.sleep(Duration.ofSeconds(1));return i;});});
}
核心優勢:
- 輕量級線程,可創建數百萬個而不會耗盡系統資源
- 簡化高吞吐量并發應用程序的編寫
- 與現有Java代碼無縫兼容,使用相同的Thread API
- 顯著減少編寫、維護和觀察高吞吐量并發應用程序的工作量
二、序列集合(Sequenced Collections)
JDK 21引入了一套新的接口來表示具有定義順序的集合:
interface SequencedCollection<E> extends Collection<E> {// 新增方法SequencedCollection<E> reversed();void addFirst(E);void addLast(E);E getFirst();E getLast();E removeFirst();E removeLast();
}
具體實現:
SequencedCollection
- 有序集合(如List)SequencedSet
- 有序且不重復的集合(如LinkedHashSet)SequencedMap
- 有序映射(如LinkedHashMap)
使用示例:
List<Integer> list = new ArrayList<>(List.of(1, 2, 3));// 新方法
list.getFirst(); // 1
list.getLast(); // 3var reversed = list.reversed(); // [3, 2, 1]
三、分代ZGC(Generational ZGC)
JDK 21對Z垃圾收集器進行了重大改進,引入了分代收集:
主要改進:
- 通過區分年輕代和老年代對象提高垃圾收集效率
- 減少垃圾收集的開銷,特別是對于分配率高的應用程序
- 保持ZGC的低延遲特性(暫停時間通常小于1毫秒)
- 可通過
-XX:+ZGenerational
標志啟用
四、模式匹配的增強
1. 記錄模式(Record Patterns)正式發布
record Point(int x, int y) {}static void printSum(Object obj) {if (obj instanceof Point(int x, int y)) {System.out.println(x + y);}
}
2. switch模式匹配增強
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();};
}
五、字符串模板(預覽特性)
JDK 21引入了字符串模板(預覽),簡化字符串插值和復雜字符串的構建:
String name = "Joan";
String info = STR."My name is \{name}";
// 結果: "My name is Joan"// 復雜示例
String title = "My Web Page";
String text = "Hello, world";
String html = STR."""<html><head><title>\{title}</title></head><body><p>\{text}</p></body></html>""";
六、外部函數與內存API(正式發布)
替代JNI的更安全、更高效的方式:
// 1. 在Java代碼中鏈接到C庫函數
Linker linker = Linker.nativeLinker();
SymbolLookup stdlib = linker.defaultLookup();
MethodHandle strlen = linker.downcallHandle(stdlib.lookup("strlen").get(),FunctionDescriptor.of(JAVA_LONG, ADDRESS)
);// 2. 使用try-with-resources管理原生內存
try (Arena arena = Arena.ofConfined()) {MemorySegment str = arena.allocateUtf8String("Hello");long len = (long) strlen.invoke(str);System.out.println(len); // 5
}
七、未命名模式和變量(預覽)
簡化模式匹配并減少不必要的變量命名:
// 舊方式
if (obj instanceof Point p) {System.out.println(p.x());
}// 新方式 - 不需要命名變量
if (obj instanceof Point(_, int y)) {System.out.println("y=" + y);
}// 未命名變量示例
try {int res = calculate();
} catch (Exception _) { // 忽略異常細節System.out.println("計算出錯");
}
八、未命名類和實例main方法(預覽)
簡化入門程序編寫:
// 傳統方式
public class HelloWorld {public static void main(String[] args) {System.out.println("Hello, World!");}
}// 新方式(預覽)
void main() {System.out.println("Hello, World!");
}
九、作用域值(Scoped Values)預覽
替代線程局部變量的更好選擇:
final static ScopedValue<...> V = ScopedValue.newInstance();// 在作用域內設置值
ScopedValue.where(V, <value>).run(() -> { ... V.get() ... });
優勢:
- 不可變,更安全
- 生命周期有限,僅限于動態范圍
- 子線程自動繼承
十、其他重要改進
- 密鑰封裝機制API:用于安全密鑰交換的加密功能
- 準備禁止動態加載代理:為未來版本默認禁止動態加載代理做準備
- 性能改進:包括G1垃圾收集器的優化和向量API的增強
- Linux/RISC-V移植:正式支持RISC-V架構
總結
JDK 21作為長期支持版本,為Java開發者帶來了眾多強大的新特性和改進。從革命性的虛擬線程到實用的序列集合,從模式匹配的增強到字符串模板的引入,這些特性共同推動Java平臺向前邁進了一大步。
對于開發者而言,現在是時候開始探索這些新特性,評估它們如何能夠提升現有應用程序的性能和開發效率。特別是虛擬線程和分代ZGC等特性,有望顯著改善高并發應用程序的性能和可維護性。
隨著Java的持續演進,JDK 21再次證明了Java平臺在現代軟件開發中的活力和創新精神。