一、前言
JDK 21 于 2023 年 9 月发布,作为目前讨论热度最高的JDK,虽然大家都开玩笑说你发任你发,我用Java8
,但是作为一个Javaer,对JDK21的新特性还是要有所了解的。
以下是 JDK 21 的新功能列表:
- 虚拟线程
- 序列集合
- 记录模式
- 字符串模板(预览)
- 未命名模式和变量(预览)
- 未命名类和实例主要方法(预览)
- 作用域值(预览)
- 结构化并发(预览)
JDK21下载地址:JDK官网
安装过程在这里就不赘述了,正常【下一步】就行了。
二、新特性体验
1. switch 模式匹配
可以通过switch表达式和语句的模式匹配来增强Java编程语言,可以针对多个模式测试表达式,每个模式都有一个特定的操作,从而可以简洁、安全地表达复杂的面向数据的查询。
1.1 支持返回值,不用写break
示例代码:
public class SwitchTest {public static void main(String[] args) {String unit = "cm";String str = switch (unit) {case "cm" -> "厘米";case "m" -> "米";case "mm" -> "毫米";case "km" -> "千米";default -> "错误";};System.out.println(str);}
}
测试结果:
注意:如果执行结果乱码,可以参考如下操作进行:
-
增加VM参数
-
修改文件编码
1.2 如果需要执行多行代码再返回,可使用yield关键字
示例代码:
public class SwitchTest {public static void main(String[] args) {String unit = "cm";String str = switch (unit) {case "cm" -> {System.out.println("我在测试呢...");yield "厘米";}case "m" -> "米";case "mm" -> "毫米";case "km" -> "千米";default -> "错误";};System.out.println(str);}
}
1.3 多值匹配
示例代码:
public class SwitchTest {public static void main(String[] args) {String unit = "cm";String str = switch (unit) {case "cm", "m" -> "厘米";case "mm" -> "毫米";case "km" -> "千米";default -> "错误";};System.out.println(str);}
}
1.4 null值处理
示例代码:
public class SwitchTest {public static void main(String[] args) {String unit = null;String str = switch (unit) {case "cm", "m" -> "厘米";case "mm" -> "毫米";case "km" -> "千米";case null -> "未知";default -> "错误";};System.out.println(str);}
}
1.5 匹配增强
示例代码:
public class SwitchTest {public static void main(String[] args) {Double obj = 0.0d;String str = 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();};System.out.println(str);}
}
2. 记录模式
记录模式,也就是记录模式匹配,英文为“Record Patterns”,记录模式匹配是指自动匹配Record记录类,从而简化代码。Record记录会自动生成了构造函数、getter、equals、hashCode、toString等方法,简化代码的编写,类似于lombok插件的@Data注解,但是对象属性只读,只有get方法,没有set方法。
-
使用class
public class User {private String name;private Integer age;public User(String name, Integer age) {this.name = name;this.age = age;}public String getName() {return name;}public Integer getAge() {return age;}}
-
使用record
public record User(String name, Integer age) { }
3. 字符串模板
示例代码:
public class StrTest {public static void main(String[] args) {String name = "JDK21";String message = STR."Hello \{name}!";System.out.println(message);}
}
注意这是预览功能,默认禁用,我们需要使用--enable-preview
启用字符串模板。
在Idea中,我们需要额外设置:
--enable-preview --source 21 -Xlint:preview
4. 顺序集合
SequencedSet 接口对于具有有序元素的 Set 非常有用,特别是当您必须执行某些操作(例如检索或删除第一个或最后一个索引处的元素)时。它还提供了一种反转元素的方法。
-
List
import java.util.LinkedHashSet; import java.util.SequencedSet;public class ListTest {public static void main(String[] args) {SequencedSet<String> values = new LinkedHashSet<>();values.add("one");values.add("two");System.out.println(values); // [one, two]values.addFirst("zero");System.out.println(values); // [zero, one, two]values.addFirst("one");System.out.println(values); // [one, zero, two]values.addLast("three");System.out.println(values); // [one, zero, two, three]SequencedSet<String> reversedSet = values.reversed();System.out.println(reversedSet); // [three, two, zero, one]} }
-
Map
import java.util.LinkedHashMap; import java.util.Map; import java.util.SequencedMap;public class MapTest {public static void main(String[] args) {SequencedMap<String, Integer> myMap = new LinkedHashMap<>();myMap.put("one", 1);myMap.put("two", 2);System.out.println(myMap); // {one=1, two=2}Map.Entry<String, Integer> firstEntry = myMap.firstEntry();System.out.println(firstEntry); // one=1Map.Entry<String, Integer> lastEntry = myMap.lastEntry();System.out.println(lastEntry); // two=2myMap.putFirst("zero", 0);System.out.println(myMap); // {zero=0, one=1, two=2}myMap.putFirst("one", -1);System.out.println(myMap); // {one=-1, zero=0, two=2}Map.Entry<String, Integer> polledFirstEntry = myMap.pollFirstEntry();System.out.println(polledFirstEntry); // one=-1System.out.println(myMap); // {zero=0, two=2}SequencedMap<String, Integer> reversedMap = myMap.reversed();System.out.println(reversedMap); // {two=2, zero=0}} }
5. 虚拟线程
虚拟线程是Jdk21的重头戏,从 Java 代码的角度来看,虚拟线程感觉就像普通线程,但它们没有 1:1 映射到操作系统/平台线程。它是从虚拟线程到载体线程进而到操作系统线程的M:N映射。
虚拟线程的一些优点:
-
提高应用程序吞吐量
-
提高应用程序可用性
-
减少内存消耗
示例代码:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class VirtualThreadsTest {public static void main(String[] args) {ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();for (int i = 0; i < 10; i++) {int taskId = i;executor.execute(() -> {System.out.println("Task " + taskId + " is running on virtual thread: " + Thread.currentThread().getName());});}try {Thread.sleep(2000L);} catch (InterruptedException e) {e.printStackTrace();}executor.shutdown();}}