@@ -9,7 +9,7 @@ JDK 21 于 2023 年 9 月 19 日 发布,这是一个非常重要的版本,
9
9
10
10
JDK21 是 LTS(长期支持版),至此为止,目前有 JDK8、JDK11、JDK17 和 JDK21 这四个长期支持版了。
11
11
12
- JDK 21 共有 15 个新特性:
12
+ JDK 21 共有 15 个新特性,这篇文章会挑选其中较为重要的一些新特性进行详细介绍 :
13
13
14
14
- [ JEP 430:String Templates(字符串模板)] ( https://openjdk.org/jeps/430 ) (预览)
15
15
- [ JEP 431:Sequenced Collections(序列化集合)] ( https://openjdk.org/jeps/431 )
@@ -18,8 +18,16 @@ JDK 21 共有 15 个新特性:
18
18
19
19
- [ JEP 440:Record Patterns(记录模式)] ( https://openjdk.org/jeps/440 )
20
20
21
+ - [ JEP 441:Pattern Matching for switch(switch 的模式匹配)] ( https://openjdk.org/jeps/442 )
22
+
23
+ - [ JEP 442:Foreign Function & Memory API(外部函数和内存 API)] ( https://openjdk.org/jeps/442 ) (第三次预览)
24
+
25
+ - [ JEP 443:Unnamed Patterns and Variables(未命名模式和变量] ( https://openjdk.org/jeps/443 ) (预览)
26
+
21
27
- [ JEP 444:Virtual Threads(虚拟线程)] ( https://openjdk.org/jeps/444 )
22
28
29
+ - [ JEP 445:Unnamed Classes and Instance Main Methods(未命名类和实例 main 方法 )] ( https://openjdk.org/jeps/445 ) (预览)
30
+
23
31
## JEP 430:字符串模板(预览)
24
32
25
33
String Templates(字符串模板) 目前仍然是 JDK 21 中的一个预览功能。
@@ -119,7 +127,134 @@ String time = STR."The current time is \{
119
127
120
128
## JEP431:序列化集合
121
129
122
- JDK 21 引入了一种新的集合类型:** Sequenced Collections(序列化集合)** 。
130
+ JDK 21 引入了一种新的集合类型:** Sequenced Collections(序列化集合,也叫有序集合)** ,这是一种具有确定出现顺序(encounter order)的集合(无论我们遍历这样的集合多少次,元素的出现顺序始终是固定的)。序列化集合提供了处理集合的第一个和最后一个元素以及反向视图(与原始集合相反的顺序)的简单方法。
131
+
132
+ Sequenced Collections 包括以下三个接口:
133
+
134
+ - [ ` SequencedCollection ` ] ( https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/SequencedCollection.html )
135
+ - [ ` SequencedSet ` ] ( https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/SequencedSet.html )
136
+ - [ ` SequencedMap ` ] ( https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/SequencedMap.html )
137
+
138
+ ` SequencedCollection ` 接口继承了 ` Collection ` 接口, 提供了在集合两端访问、添加或删除元素以及获取集合的反向视图的方法。
139
+
140
+ ``` java
141
+ interface SequencedCollection <E> extends Collection<E > {
142
+
143
+ // New Method
144
+
145
+ SequencedCollection<E > reversed ();
146
+
147
+ // Promoted methods from Deque<E>
148
+
149
+ void addFirst (E );
150
+ void addLast (E );
151
+
152
+ E getFirst ();
153
+ E getLast ();
154
+
155
+ E removeFirst ();
156
+ E removeLast ();
157
+ }
158
+ ```
159
+
160
+ ` List ` 和 ` Deque ` 接口实现了` SequencedCollection ` 接口。
161
+
162
+ 这里以 ` ArrayList ` 为例,演示一下实际使用效果:
163
+
164
+ ``` java
165
+ ArrayList<Integer > arrayList = new ArrayList<> ();
166
+
167
+ arrayList. add(1 ); // List contains: [1]
168
+
169
+ arrayList. addFirst(0 ); // List contains: [0, 1]
170
+ arrayList. addLast(2 ); // List contains: [0, 1, 2]
171
+
172
+ Integer firstElement = arrayList. getFirst(); // 0
173
+ Integer lastElement = arrayList. getLast(); // 2
174
+
175
+ List<Integer > reversed = arrayList. reversed();
176
+ System . out. println(reversed); // Prints [2, 1, 0]
177
+ ```
178
+
179
+ ` SequencedSet ` 接口直接继承了 ` SequencedCollection ` 接口并重写了 ` reversed() ` 方法。
180
+
181
+ ``` java
182
+ interface SequencedSet <E> extends SequencedCollection<E > , Set<E > {
183
+
184
+ SequencedSet<E > reversed ();
185
+ }
186
+ ```
187
+
188
+ ` SortedSet ` 和 ` LinkedHashSet ` 实现了` SequencedSet ` 接口。
189
+
190
+ 这里以 ` LinkedHashSet ` 为例,演示一下实际使用效果:
191
+
192
+ ``` java
193
+ LinkedHashSet<Integer > linkedHashSet = new LinkedHashSet<> (List . of(1 , 2 , 3 ));
194
+
195
+ Integer firstElement = linkedHashSet. getFirst(); // 1
196
+ Integer lastElement = linkedHashSet. getLast(); // 3
197
+
198
+ linkedHashSet. addFirst(0 ); // List contains: [0, 1, 2, 3]
199
+ linkedHashSet. addLast(4 ); // List contains: [0, 1, 2, 3, 4]
200
+
201
+ System . out. println(linkedHashSet. reversed()); // Prints [5, 3, 2, 1, 0]
202
+ ```
203
+
204
+ ` SequencedMap ` 接口继承了 ` Map ` 接口, 提供了在集合两端访问、添加或删除键值对、获取包含 key 的 ` SequencedSet ` 、包含 value 的 ` SequencedCollection ` 、包含 entry(键值对) 的 ` SequencedSet ` 以及获取集合的反向视图的方法。
205
+
206
+ ``` java
207
+ interface SequencedMap <K,V> extends Map<K ,V > {
208
+
209
+ // New Methods
210
+
211
+ SequencedMap<K ,V > reversed ();
212
+
213
+ SequencedSet<K > sequencedKeySet ();
214
+ SequencedCollection<V > sequencedValues ();
215
+ SequencedSet<Entry<K ,V > > sequencedEntrySet ();
216
+
217
+ V putFirst (K , V );
218
+ V putLast (K , V );
219
+
220
+
221
+ // Promoted Methods from NavigableMap<K, V>
222
+
223
+ Entry<K , V > firstEntry ();
224
+ Entry<K , V > lastEntry ();
225
+
226
+ Entry<K , V > pollFirstEntry ();
227
+ Entry<K , V > pollLastEntry ();
228
+ }
229
+ ```
230
+
231
+ ` SortedMap ` 和` LinkedHashMap ` 实现了` SequencedMap ` 接口。
232
+
233
+ 这里以 ` LinkedHashMap ` 为例,演示一下实际使用效果:
234
+
235
+ ``` java
236
+ LinkedHashMap<Integer , String > map = new LinkedHashMap<> ();
237
+
238
+ map. put(1 , " One" );
239
+ map. put(2 , " Two" );
240
+ map. put(3 , " Three" );
241
+
242
+ map. firstEntry(); // 1=One
243
+ map. lastEntry(); // 3=Three
244
+
245
+ System . out. println(map); // {1=One, 2=Two, 3=Three}
246
+
247
+ Map . Entry<Integer , String > first = map. pollFirstEntry(); // 1=One
248
+ Map . Entry<Integer , String > last = map. pollLastEntry(); // 3=Three
249
+
250
+ System . out. println(map); // {2=Two}
251
+
252
+ map. putFirst(1 , " One" ); // {1=One, 2=Two}
253
+ map. putLast(3 , " Three" ); // {1=One, 2=Two, 3=Three}
254
+
255
+ System . out. println(map); // {1=One, 2=Two, 3=Three}
256
+ System . out. println(map. reversed()); // {3=Three, 2=Two, 1=One}
257
+ ```
123
258
124
259
## JEP 439:分代 ZGC
125
260
@@ -144,6 +279,63 @@ java -XX:+UseZGC -XX:+ZGenerational ...
144
279
145
280
[ Java 20 新特性概览] ( ./java20.md ) 已经详细介绍过记录模式,这里就不重复了。
146
281
282
+ ## JEP 441:switch 的模式匹配
283
+
284
+ 增强 Java 中的 switch 表达式和语句,允许在 case 标签中使用模式。当模式匹配时,执行 case 标签对应的代码。
285
+
286
+ 在下面的代码中,switch 表达式使用了类型模式来进行匹配。
287
+
288
+ ``` java
289
+ static String formatterPatternSwitch(Object obj) {
290
+ return switch (obj) {
291
+ case Integer i - > String . format(" int %d" , i);
292
+ case Long l - > String . format(" long %d" , l);
293
+ case Double d - > String . format(" double %f" , d);
294
+ case String s - > String . format(" String %s" , s);
295
+ default - > obj. toString();
296
+ };
297
+ }
298
+ ```
299
+
300
+ ## JEP 442: 外部函数和内存 API(第三次预览)
301
+
302
+ Java 程序可以通过该 API 与 Java 运行时之外的代码和数据进行互操作。通过高效地调用外部函数(即 JVM 之外的代码)和安全地访问外部内存(即不受 JVM 管理的内存),该 API 使 Java 程序能够调用本机库并处理本机数据,而不会像 JNI 那样危险和脆弱。
303
+
304
+ 外部函数和内存 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 ) 提出。
305
+
306
+ 在 [ Java 19 新特性概览] ( ./java19.md ) 中,我有详细介绍到外部函数和内存 API,这里就不再做额外的介绍了。
307
+
308
+ ## JEP 443:未命名模式和变量(预览)
309
+
310
+ 未命名模式和变量使得我们可以使用下划线 ` _ ` 表示未命名的变量以及模式匹配时不使用的组件,旨在提高代码的可读性和可维护性。
311
+
312
+ 未命名变量的典型场景是 ` try-with-resources ` 语句、 ` catch ` 子句中的异常变量和` for ` 循环。当变量不需要使用的时候就可以使用下划线 ` _ ` 代替,这样清晰标识未被使用的变量。
313
+
314
+ ``` java
315
+ try (var _ = ScopedContext . acquire()) {
316
+ // No use of acquired resource
317
+ }
318
+ try { ... }
319
+ catch (Exception _) { ... }
320
+ catch (Throwable _) { ... }
321
+
322
+ for (int i = 0 , _ = runOnce(); i < arr. length; i++ ) {
323
+ ...
324
+ }
325
+ ```
326
+
327
+ 未命名模式是一个无条件的模式,并不绑定任何值。未命名模式变量出现在类型模式中。
328
+
329
+ ``` java
330
+ if (r instanceof ColoredPoint(_, Color c)) { ... c ... }
331
+
332
+ switch (b) {
333
+ case Box(RedBall _), Box(BlueBall _) - > processBox(b);
334
+ case Box(GreenBall _) - > stopProcessing();
335
+ case Box(_) - > pickAnotherBox();
336
+ }
337
+ ```
338
+
147
339
## JEP 444:虚拟线程
148
340
149
341
虚拟线程是一项重量级的更新,一定一定要重视!
@@ -152,6 +344,39 @@ java -XX:+UseZGC -XX:+ZGenerational ...
152
344
153
345
[ Java 20 新特性概览] ( ./java20.md ) 已经详细介绍过虚拟线程,这里就不重复了。
154
346
347
+ ## JEP 445:未命名类和实例 main 方法 (预览)
348
+
349
+ 这个特性主要简化了 ` main ` 方法的的声明。对于 Java 初学者来说,这个 ` main ` 方法的声明引入了太多的 Java 语法概念,不利于初学者快速上手。
350
+
351
+ 没有使用该特性之前定义一个 ` main ` 方法:
352
+
353
+ ``` java
354
+ public class HelloWorld {
355
+ public static void main (String [] args ) {
356
+ System . out. println(" Hello, World!" );
357
+ }
358
+ }
359
+ ```
360
+
361
+ 使用该新特性之后定义一个 ` main ` 方法:
362
+
363
+ ``` java
364
+ class HelloWorld {
365
+ void main () {
366
+ System . out. println(" Hello, World!" );
367
+ }
368
+ }
369
+ ```
370
+
371
+ 进一步精简(未命名的类允许我们不定义类名):
372
+
373
+ ``` java
374
+ void main() {
375
+ System . out. println(" Hello, World!" );
376
+ }
377
+ ```
378
+
155
379
## 参考
156
380
157
381
- Java 21 String Templates:< https://howtodoinjava.com/java/java-string-templates/ >
382
+ - Java 21 Sequenced Collections:https://howtodoinjava.com/java/sequenced-collections/
0 commit comments