---
title: Java 21 æ°ç¹æ§æ¦è§(éè¦)
description: æ¦è§ JDK 21 çå
³é®æ°ç¹æ§ä¸å®è·µå½±åï¼éç¹ä»ç»å符串模æ¿ãSequenced Collectionsãå代 ZGCãèæçº¿ç¨çã
category: Java
tag:
- Javaæ°ç¹æ§
head:
- - meta
- name: keywords
content: Java 21,JDK21,LTS,å符串模æ¿,Sequenced Collections,å代 ZGC,è®°å½æ¨¡å¼,switch 模å¼å¹é
,èæçº¿ç¨,å¤é¨å½æ°ä¸å
å API
---
JDK 21 äº 2023 å¹´ 9 æ 19 æ¥ åå¸ï¼è¿æ¯ä¸ä¸ªé常éè¦ççæ¬ï¼éç¨ç¢å¼ã
JDK 21 æ¯ LTSï¼é¿ææ¯æçï¼ï¼è³æ¤ä¸ºæ¢ï¼ç®åæ JDK8ãJDK11ãJDK17 å JDK21 è¿åä¸ªé¿ææ¯æçäºã
JDK 21 å
±æ 15 个æ°ç¹æ§ï¼è¿ç¯æç« 伿éå
¶ä¸è¾ä¸ºéè¦çä¸äºæ°ç¹æ§è¿è¡è¯¦ç»ä»ç»ï¼
- [JEP 430: String Templatesï¼å符串模æ¿ï¼](https://openjdk.org/jeps/430)ï¼é¢è§ï¼
- [JEP 431: Sequenced Collectionsï¼åºååéåï¼](https://openjdk.org/jeps/431)
- [JEP 439: Generational ZGCï¼å代 ZGCï¼](https://openjdk.org/jeps/439)
- [JEP 440: Record Patternsï¼è®°å½æ¨¡å¼ï¼](https://openjdk.org/jeps/440)
- [JEP 441: Pattern Matching for switchï¼switch çæ¨¡å¼å¹é
ï¼](https://openjdk.org/jeps/441)
- [JEP 442: Foreign Function & Memory APIï¼å¤é¨å½æ°åå
å APIï¼](https://openjdk.org/jeps/442)ï¼ç¬¬ä¸æ¬¡é¢è§ï¼
- [JEP 443: Unnamed Patterns and Variablesï¼æªå½å模å¼ååéï¼](https://openjdk.org/jeps/443)ï¼é¢è§ï¼
- [JEP 444: Virtual Threadsï¼èæçº¿ç¨ï¼](https://openjdk.org/jeps/444)
- [JEP 445: Unnamed Classes and Instance Main Methodsï¼æªå½åç±»åå®ä¾ main æ¹æ³ï¼](https://openjdk.org/jeps/445)ï¼é¢è§ï¼
ä¸å¾æ¯ä» JDK 8 å° JDK 24 æ¯ä¸ªçæ¬çæ´æ°å¸¦æ¥çæ°ç¹æ§æ°éåæ´æ°æ¶é´ï¼

## JEP 430: String Templatesï¼å符串模æ¿ï¼é¢è§ï¼
String Templates(å符串模æ¿) ç®åä»ç¶æ¯ JDK 21 ä¸çä¸ä¸ªé¢è§åè½ã
String Templates æä¾äºä¸ç§æ´ç®æ´ãæ´ç´è§çæ¹å¼æ¥å¨ææå»ºå符串ãéè¿ä½¿ç¨å ä½ç¬¦`${}`ï¼æä»¬å¯ä»¥å°åéçå¼ç´æ¥åµå
¥å°å符串ä¸ï¼èä¸éè¦æå¨å¤çãå¨è¿è¡æ¶ï¼Java ç¼è¯å¨ä¼å°è¿äºå ä½ç¬¦æ¿æ¢ä¸ºå®é
çåéå¼ãå¹¶ä¸ï¼è¡¨è¾¾å¼æ¯æå±é¨åéãéæ/ééæå段çè³æ¹æ³ã计ç®ç»æçç¹æ§ã
å®é
ä¸ï¼String Templatesï¼å符串模æ¿ï¼å¨å¤§å¤æ°ç¼ç¨è¯è¨ä¸é½åå¨:
```typescript
"Greetings {{ name }}!"; //Angular
`Greetings ${ name }!`; //Typescript
$"Greetings { name }!" //Visual basic
f"Greetings { name }!" //Python
```
Java 卿²¡æ String Templates ä¹åï¼æä»¬é常使ç¨åç¬¦ä¸²æ¼æ¥ææ ¼å¼åæ¹æ³æ¥æå»ºå符串ï¼
```java
//concatenation
message = "Greetings " + name + "!";
//String.format()
message = String.format("Greetings %s!", name); //concatenation
//MessageFormat
message = new MessageFormat("Greetings {0}!").format(name);
//StringBuilder
message = new StringBuilder().append("Greetings ").append(name).append("!").toString();
```
è¿äºæ¹æ³æå¤æå°é½åå¨ä¸äºç¼ºç¹ï¼æ¯å¦é¾ä»¥é
读ãåé¿ã夿ã
Java ä½¿ç¨ String Templates è¿è¡åç¬¦ä¸²æ¼æ¥ï¼å¯ä»¥ç´æ¥å¨å符串ä¸åµå
¥è¡¨è¾¾å¼ï¼èæ éè¿è¡é¢å¤çå¤çï¼
```java
String message = STR."Greetings \{name}!";
```
å¨ä¸é¢ç模æ¿è¡¨è¾¾å¼ä¸ï¼
- STR æ¯æ¨¡æ¿å¤çå¨ã
- `\{name}`为表达å¼ï¼è¿è¡æ¶ï¼è¿äºè¡¨è¾¾å¼å°è¢«ç¸åºçåé弿¿æ¢ã
Java ç®åæ¯æä¸ç§æ¨¡æ¿å¤çå¨ï¼
- STRï¼èªå¨æ§è¡å符串æå¼ï¼å³å°æ¨¡æ¿ä¸çæ¯ä¸ªåµå
¥å¼è¡¨è¾¾å¼æ¿æ¢ä¸ºå
¶å¼ï¼è½¬æ¢ä¸ºå符串ï¼ã
- FMTï¼å STR 类似ï¼ä½æ¯å®è¿å¯ä»¥æ¥åæ ¼å¼è¯´æç¬¦ï¼è¿äºæ ¼å¼è¯´æç¬¦åºç°å¨åµå
¥å¼è¡¨è¾¾å¼ç左边ï¼ç¨æ¥æ§å¶è¾åºçæ ·å¼ã
- RAWï¼ä¸ä¼å STR å FMT 模æ¿å¤çå¨é£æ ·èªå¨å¤çå符串模æ¿ï¼èæ¯è¿åä¸ä¸ª `StringTemplate` 对象ï¼è¿ä¸ªå¯¹è±¡å
å«äºæ¨¡æ¿ä¸çææ¬å表达å¼çä¿¡æ¯ã
```java
String name = "Lokesh";
//STR
String message = STR."Greetings \{name}.";
//FMT
String message = FMT."Greetings %-12s\{name}.";
//RAW
StringTemplate st = RAW."Greetings \{name}.";
String message = STR.process(st);
```
é¤äº JDK èªå¸¦çä¸ç§æ¨¡æ¿å¤çå¨å¤ï¼ä½ è¿å¯ä»¥å®ç° `StringTemplate.Processor` æ¥å£æ¥å建èªå·±ç模æ¿å¤çå¨ï¼åªéè¦ç»§æ¿ `StringTemplate.Processor`æ¥å£ï¼ç¶åå®ç° `process` æ¹æ³å³å¯ã
æä»¬å¯ä»¥ä½¿ç¨å±é¨åéãéæ/ééæå段çè³æ¹æ³ä½ä¸ºåµå
¥è¡¨è¾¾å¼ï¼
```java
//variable
message = STR."Greetings \{name}!";
//method
message = STR."Greetings \{getName()}!";
//field
message = STR."Greetings \{this.name}!";
```
è¿å¯ä»¥å¨è¡¨è¾¾å¼ä¸æ§è¡è®¡ç®å¹¶æå°ç»æï¼
```java
int x = 10, y = 20;
String s = STR."\{x} + \{y} = \{x + y}"; //"10 + 20 = 30"
```
ä¸ºäºæé«å¯è¯»æ§ï¼æä»¬å¯ä»¥å°åµå
¥ç表达å¼åæå¤è¡:
```java
String time = STR."The current time is \{
//sample comment - current time in HH:mm:ss
DateTimeFormatter
.ofPattern("HH:mm:ss")
.format(LocalTime.now())
}.";
```
## JEP 431: Sequenced Collectionsï¼åºååéåï¼
JDK 21 å¼å
¥äºä¸ç§æ°çéåç±»åï¼**Sequenced Collectionsï¼åºååéåï¼ä¹å«æåºéåï¼**ï¼è¿æ¯ä¸ç§å
·æç¡®å®åºç°é¡ºåºï¼encounter orderï¼çéåï¼æ 论æä»¬éåè¿æ ·çéåå¤å°æ¬¡ï¼å
ç´ çåºç°é¡ºåºå§ç»æ¯åºå®çï¼ãåºååéåæä¾äºå¤çéåç第ä¸ä¸ªåæåä¸ä¸ªå
ç´ ä»¥åååè§å¾ï¼ä¸åå§éåç¸åç顺åºï¼çç®åæ¹æ³ã
Sequenced Collections å
æ¬ä»¥ä¸ä¸ä¸ªæ¥å£ï¼
- [`SequencedCollection`](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/SequencedCollection.html)
- [`SequencedSet`](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/SequencedSet.html)
- [`SequencedMap`](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/SequencedMap.html)
`SequencedCollection` æ¥å£ç»§æ¿äº `Collection`æ¥å£ï¼ æä¾äºå¨éå两端访é®ãæ·»å æå é¤å
ç´ ä»¥åè·åéåçååè§å¾çæ¹æ³ã
```java
interface SequencedCollection extends Collection {
// New Method
SequencedCollection reversed();
// Promoted methods from Deque
void addFirst(E);
void addLast(E);
E getFirst();
E getLast();
E removeFirst();
E removeLast();
}
```
`List` å `Deque` æ¥å£å®ç°äº`SequencedCollection` æ¥å£ã
è¿é以 `ArrayList` 为ä¾ï¼æ¼ç¤ºä¸ä¸å®é
ä½¿ç¨ææï¼
```java
ArrayList arrayList = new ArrayList<>();
arrayList.add(1); // List contains: [1]
arrayList.addFirst(0); // List contains: [0, 1]
arrayList.addLast(2); // List contains: [0, 1, 2]
Integer firstElement = arrayList.getFirst(); // 0
Integer lastElement = arrayList.getLast(); // 2
List reversed = arrayList.reversed();
System.out.println(reversed); // Prints [2, 1, 0]
```
`SequencedSet`æ¥å£ç´æ¥ç»§æ¿äº `SequencedCollection` æ¥å£å¹¶éåäº `reversed()` æ¹æ³ã
```java
interface SequencedSet extends SequencedCollection, Set {
SequencedSet reversed();
}
```
`SortedSet` å `LinkedHashSet` å®ç°äº`SequencedSet`æ¥å£ã
è¿é以 `LinkedHashSet` 为ä¾ï¼æ¼ç¤ºä¸ä¸å®é
ä½¿ç¨ææï¼
```java
LinkedHashSet linkedHashSet = new LinkedHashSet<>(List.of(1, 2, 3));
Integer firstElement = linkedHashSet.getFirst(); // 1
Integer lastElement = linkedHashSet.getLast(); // 3
linkedHashSet.addFirst(0); //List contains: [0, 1, 2, 3]
linkedHashSet.addLast(4); //List contains: [0, 1, 2, 3, 4]
System.out.println(linkedHashSet.reversed()); //Prints [4, 3, 2, 1, 0]
```
`SequencedMap` æ¥å£ç»§æ¿äº `Map`æ¥å£ï¼ æä¾äºå¨éå两端访é®ãæ·»å æå é¤é®å¼å¯¹ãè·åå
å« key ç `SequencedSet`ãå
å« value ç `SequencedCollection`ãå
å« entryï¼é®å¼å¯¹ï¼ ç `SequencedSet`以åè·åéåçååè§å¾çæ¹æ³ã
```java
interface SequencedMap extends Map {
// New Methods
SequencedMap reversed();
SequencedSet sequencedKeySet();
SequencedCollection sequencedValues();
SequencedSet> sequencedEntrySet();
V putFirst(K, V);
V putLast(K, V);
// Promoted Methods from NavigableMap
Entry firstEntry();
Entry lastEntry();
Entry pollFirstEntry();
Entry pollLastEntry();
}
```
`SortedMap` å`LinkedHashMap` å®ç°äº`SequencedMap` æ¥å£ã
è¿é以 `LinkedHashMap` 为ä¾ï¼æ¼ç¤ºä¸ä¸å®é
ä½¿ç¨ææï¼
```java
LinkedHashMap map = new LinkedHashMap<>();
map.put(1, "One");
map.put(2, "Two");
map.put(3, "Three");
map.firstEntry(); //1=One
map.lastEntry(); //3=Three
System.out.println(map); //{1=One, 2=Two, 3=Three}
Map.Entry first = map.pollFirstEntry(); //1=One
Map.Entry last = map.pollLastEntry(); //3=Three
System.out.println(map); //{2=Two}
map.putFirst(1, "One"); //{1=One, 2=Two}
map.putLast(3, "Three"); //{1=One, 2=Two, 3=Three}
System.out.println(map); //{1=One, 2=Two, 3=Three}
System.out.println(map.reversed()); //{3=Three, 2=Two, 1=One}
```
## JEP 439: Generational ZGCï¼å代 ZGCï¼
JDK21 ä¸å¯¹ ZGC è¿è¡äºåè½æ©å±ï¼å¢å äºå代 GC åè½ãä¸è¿ï¼é»è®¤æ¯å
³éçï¼éè¦éè¿é
ç½®æå¼ï¼
```bash
// å¯ç¨å代ZGC
java -XX:+UseZGC -XX:+ZGenerational ...
```
卿ªæ¥ççæ¬ä¸ï¼å®æ¹ä¼æ ZGenerational 设为é»è®¤å¼ï¼å³é»è®¤æå¼ ZGC çå代 GCã卿´æççæ¬ä¸ï¼éå代 ZGC 就被移é¤ã
> In a future release we intend to make Generational ZGC the default, at which point -XX:-ZGenerational will select non-generational ZGC. In an even later release we intend to remove non-generational ZGC, at which point the ZGenerational option will become obsolete.
>
> å¨å°æ¥ççæ¬ä¸ï¼æä»¬æç®å° Generational ZGC ä½ä¸ºé»è®¤éé¡¹ï¼æ¤æ¶-XX:-ZGenerational å°éæ©éå代 ZGCã卿´æççæ¬ä¸ï¼æä»¬æç®ç§»é¤éå代 ZGCï¼æ¤æ¶ ZGenerational é项å°åå¾è¿æ¶ã
å代 ZGC å¯ä»¥æ¾èåå°åå¾åæ¶è¿ç¨ä¸çåé¡¿æ¶é´ï¼å¹¶æé«åºç¨ç¨åºçååºæ§è½ãè¿å¯¹äºå¤§å Java åºç¨ç¨åºåé«å¹¶ååºæ¯ä¸çæ§è½ä¼åé常æä»·å¼ã
## JEP 440: Record Patternsï¼è®°å½æ¨¡å¼ï¼
è®°å½æ¨¡å¼å¨ Java 19 è¿è¡äºç¬¬ä¸æ¬¡é¢è§ï¼ ç± [JEP 405](https://openjdk.org/jeps/405) æåºãJDK 20 䏿¯ç¬¬äºæ¬¡é¢è§ï¼ç± [JEP 432](https://openjdk.org/jeps/432) æåºãæç»ï¼è®°å½æ¨¡å¼å¨ JDK21 顺å©è½¬æ£ã
[Java 20 æ°ç¹æ§æ¦è§](./java20.md)å·²ç»è¯¦ç»ä»ç»è¿è®°å½æ¨¡å¼ï¼è¿éå°±ä¸éå¤äºã
## JEP 441: Pattern Matching for switchï¼switch çæ¨¡å¼å¹é
ï¼
å¢å¼º Java ä¸ç switch 表达å¼åè¯å¥ï¼å
è®¸å¨ case æ ç¾ä¸ä½¿ç¨æ¨¡å¼ã彿¨¡å¼å¹é
æ¶ï¼æ§è¡ case æ ç¾å¯¹åºç代ç ã
å¨ä¸é¢ç代ç ä¸ï¼switch 表达å¼ä½¿ç¨äºç±»åæ¨¡å¼æ¥è¿è¡å¹é
ã
```java
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();
};
}
```
## JEP 442: Foreign Function & Memory APIï¼å¤é¨å½æ°åå
å APIï¼ç¬¬ä¸æ¬¡é¢è§ï¼
Java ç¨åºå¯ä»¥éè¿è¯¥ API ä¸ Java è¿è¡æ¶ä¹å¤ç代ç åæ°æ®è¿è¡äºæä½ãéè¿é«æå°è°ç¨å¤é¨å½æ°ï¼å³ JVM ä¹å¤ç代ç ï¼åå®å
¨å°è®¿é®å¤é¨å
åï¼å³ä¸å JVM 管ççå
åï¼ï¼è¯¥ API 使 Java ç¨åºè½å¤è°ç¨æ¬æºåºå¹¶å¤çæ¬æºæ°æ®ï¼èä¸ä¼å JNI 飿 ·å±é©åèå¼±ã
å¤é¨å½æ°åå
å API å¨ Java 17 ä¸è¿è¡äºç¬¬ä¸è½®åµåï¼ç± [JEP 412](https://openjdk.java.net/jeps/412) æåºãJava 18 ä¸è¿è¡äºç¬¬äºæ¬¡åµåï¼ç±[JEP 419](https://openjdk.org/jeps/419) æåºãJava 19 䏿¯ç¬¬ä¸æ¬¡é¢è§ï¼ç± [JEP 424](https://openjdk.org/jeps/424) æåºãJDK 20 䏿¯ç¬¬äºæ¬¡é¢è§ï¼ç± [JEP 434](https://openjdk.org/jeps/434) æåºãJDK 21 䏿¯ç¬¬ä¸æ¬¡é¢è§ï¼ç± [JEP 442](https://openjdk.org/jeps/442) æåºã
å¨ [Java 19 æ°ç¹æ§æ¦è§](./java19.md) ä¸ï¼ææè¯¦ç»ä»ç»å°å¤é¨å½æ°åå
å APIï¼è¿éå°±ä¸ååé¢å¤çä»ç»äºã
## JEP 443: Unnamed Patterns and Variablesï¼æªå½å模å¼ååéï¼é¢è§ï¼
æªå½å模å¼ååéä½¿å¾æä»¬å¯ä»¥ä½¿ç¨ä¸å线 `_` 表示æªå½åçåé以忍¡å¼å¹é
æ¶ä¸ä½¿ç¨çç»ä»¶ï¼æ¨å¨æé«ä»£ç çå¯è¯»æ§åå¯ç»´æ¤æ§ã
æªå½ååéçå
¸ååºæ¯æ¯ `try-with-resources` è¯å¥ã `catch` åå¥ä¸çå¼å¸¸åéå`for`循ç¯ãå½åéä¸éè¦ä½¿ç¨çæ¶åå°±å¯ä»¥ä½¿ç¨ä¸å线 `_`代æ¿ï¼è¿æ ·æ¸
æ°æ è¯æªè¢«ä½¿ç¨çåéã
```java
try (var _ = ScopedContext.acquire()) {
// No use of acquired resource
}
try { ... }
catch (Exception _) { ... }
catch (Throwable _) { ... }
for (int i = 0, _ = runOnce(); i < arr.length; i++) {
...
}
```
æªå½åæ¨¡å¼æ¯ä¸ä¸ªæ æ¡ä»¶ç模å¼ï¼å¹¶ä¸ç»å®ä»»ä½å¼ãæªå½å模å¼åéåºç°å¨ç±»å模å¼ä¸ã
```java
if (r instanceof ColoredPoint(_, Color c)) { ... c ... }
switch (b) {
case Box(RedBall _), Box(BlueBall _) -> processBox(b);
case Box(GreenBall _) -> stopProcessing();
case Box(_) -> pickAnotherBox();
}
```
## JEP 444: Virtual Threadsï¼èæçº¿ç¨ï¼
èæçº¿ç¨æ¯ä¸é¡¹ééçº§çæ´æ°ï¼ä¸å®ä¸å®è¦éè§ï¼
èæçº¿ç¨å¨ Java 19 ä¸è¿è¡äºç¬¬ä¸æ¬¡é¢è§ï¼ç±[JEP 425](https://openjdk.org/jeps/425)æåºãJDK 20 䏿¯ç¬¬äºæ¬¡é¢è§ãæç»ï¼èæçº¿ç¨å¨ JDK21 顺å©è½¬æ£ã
[Java 20 æ°ç¹æ§æ¦è§](./java20.md)å·²ç»è¯¦ç»ä»ç»è¿èæçº¿ç¨ï¼è¿éå°±ä¸éå¤äºã
## JEP 445: Unnamed Classes and Instance Main Methodsï¼æªå½åç±»åå®ä¾ main æ¹æ³ï¼é¢è§ï¼
è¿ä¸ªç¹æ§ä¸»è¦ç®åäº `main` æ¹æ³ç声æãå¯¹äº Java åå¦è
æ¥è¯´ï¼è¿ä¸ª `main` æ¹æ³ç声æå¼å
¥äºå¤ªå¤ç Java è¯æ³æ¦å¿µï¼ä¸å©äºåå¦è
å¿«é䏿ã
没æä½¿ç¨è¯¥ç¹æ§ä¹åå®ä¹ä¸ä¸ª `main` æ¹æ³ï¼
```java
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
```
使ç¨è¯¥æ°ç¹æ§ä¹åå®ä¹ä¸ä¸ª `main` æ¹æ³ï¼
```java
class HelloWorld {
void main() {
System.out.println("Hello, World!");
}
}
```
è¿ä¸æ¥ç²¾ç®(æªå½åçç±»å
许æä»¬ä¸å®ä¹ç±»å)ï¼
```java
void main() {
System.out.println("Hello, World!");
}
```
## åè
- Java 21 String Templatesï¼
- Java 21 Sequenced Collectionsï¼