怎么修改网站上传附件大小,安徽网站排名优化公司,免费用搭建网站,家用电脑搭建服务器不学前沿技术与朽木浮草何异 #xff1f;Java21新特性 文章目录 不学前沿技术与朽木浮草何异 #xff1f;Java21新特性JEP 430#xff1a;字符串模板#xff08;预览#xff09;JEP431#xff1a;序列化集合JEP 439#xff1a;分代 ZGCJEP 440#xff1a;记录模式JEP 4…不学前沿技术与朽木浮草何异 Java21新特性 文章目录 不学前沿技术与朽木浮草何异 Java21新特性JEP 430字符串模板预览JEP431序列化集合JEP 439分代 ZGCJEP 440记录模式JEP 441switch 的模式匹配JEP 442: 外部函数和内存 API第三次预览JEP 443未命名模式和变量预览JEP 444虚拟线程JEP 445未命名类和实例 main 方法 预览 JDK 21 于 2023 年 9 月 19 日 发布这是一个非常重要的版本里程碑式。 JDK21 是 LTS长期支持版至此为止目前有 JDK8、JDK11、JDK17 和 JDK21 这四个长期支持版了。
JDK 21 共有 15 个新特性这篇文章会挑选其中较为重要的一些新特性进行详细介绍 JEP 430String Templates字符串模板预览 JEP 431Sequenced Collections序列化集合 JEP 439Generational ZGC分代 ZGC JEP 440Record Patterns记录模式 JEP 441Pattern Matching for switchswitch 的模式匹配 JEP 442Foreign Function Memory API外部函数和内存 API第三次预览 JEP 443Unnamed Patterns and Variables未命名模式和变量预览 JEP 444Virtual Threads虚拟线程 JEP 445Unnamed Classes and Instance Main Methods未命名类和实例 main 方法 预览
JEP 430字符串模板预览
String Templates(字符串模板) 目前仍然是 JDK 21 中的一个预览功能。
String Templates 提供了一种更简洁、更直观的方式来动态构建字符串。通过使用占位符${}我们可以将变量的值直接嵌入到字符串中而不需要手动处理。在运行时Java 编译器会将这些占位符替换为实际的变量值。并且表达式支持局部变量、静态/非静态字段甚至方法、计算结果等特性。
实际上String Templates字符串模板再大多数编程语言中都存在:
Greetings {{ name }}!; //Angular
Greetings ${ name }!; //Typescript
$Greetings { name }! //Visual basic
fGreetings { name }! //PythonJava 在没有 String Templates 之前我们通常使用字符串拼接或格式化方法来构建字符串
//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 进行字符串拼接可以直接在字符串中嵌入表达式而无需进行额外的处理
String message STR.Greetings \{name}!;在上面的模板表达式中
STR 是模板处理器。\{name}为表达式运行时这些表达式将被相应的变量值替换。
Java 目前支持三种模板处理器
STR自动执行字符串插值即将模板中的每个嵌入式表达式替换为其值转换为字符串。FMT和 STR 类似但是它还可以接受格式说明符这些格式说明符出现在嵌入式表达式的左边用来控制输出的样式RAW不会像 STR 和 FMT 模板处理器那样自动处理字符串模板而是返回一个 StringTemplate 对象这个对象包含了模板中的文本和表达式的信息
String name Lokesh;//STR
String message STR.Greetings \{name}.;//FMT
String message STR.Greetings %-12s\{name}.;//RAW
StringTemplate st RAW.Greetings \{name}.;
String message STR.process(st);除了 JDK 自带的三种模板处理器外你还可以实现 StringTemplate.Processor 接口来创建自己的模板处理器。
我们可以使用局部变量、静态/非静态字段甚至方法作为嵌入表达式
//variable
message STR.Greetings \{name}!;//method
message STR.Greetings \{getName()}!;//field
message STR.Greetings \{this.name}!;还可以在表达式中执行计算并打印结果
int x 10, y 20;
String s STR.\{x} \{y} \{x y}; //10 20 30为了提高可读性我们可以将嵌入的表达式分成多行:
String time STR.The current time is \{//sample comment - current time in HH:mm:ssDateTimeFormatter.ofPattern(HH:mm:ss).format(LocalTime.now())}.;JEP431序列化集合
JDK 21 引入了一种新的集合类型Sequenced Collections序列化集合也叫有序集合这是一种具有确定出现顺序encounter order的集合无论我们遍历这样的集合多少次元素的出现顺序始终是固定的。序列化集合提供了处理集合的第一个和最后一个元素以及反向视图与原始集合相反的顺序的简单方法。
Sequenced Collections 包括以下三个接口
SequencedCollectionSequencedSetSequencedMap
SequencedCollection 接口继承了 Collection接口 提供了在集合两端访问、添加或删除元素以及获取集合的反向视图的方法。
interface SequencedCollectionE extends CollectionE {// New MethodSequencedCollectionE reversed();// Promoted methods from DequeEvoid addFirst(E);void addLast(E);E getFirst();E getLast();E removeFirst();E removeLast();
}List 和 Deque 接口实现了SequencedCollection 接口。
这里以 ArrayList 为例演示一下实际使用效果
ArrayListInteger 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(); // 2ListInteger reversed arrayList.reversed();
System.out.println(reversed); // Prints [2, 1, 0]SequencedSet接口直接继承了 SequencedCollection 接口并重写了 reversed() 方法。
interface SequencedSetE extends SequencedCollectionE, SetE {SequencedSetE reversed();
}SortedSet 和 LinkedHashSet 实现了SequencedSet接口。
这里以 LinkedHashSet 为例演示一下实际使用效果
LinkedHashSetInteger linkedHashSet new LinkedHashSet(List.of(1, 2, 3));Integer firstElement linkedHashSet.getFirst(); // 1
Integer lastElement linkedHashSet.getLast(); // 3linkedHashSet.addFirst(0); //List contains: [0, 1, 2, 3]
linkedHashSet.addLast(4); //List contains: [0, 1, 2, 3, 4]System.out.println(linkedHashSet.reversed()); //Prints [5, 3, 2, 1, 0]SequencedMap 接口继承了 Map接口 提供了在集合两端访问、添加或删除键值对、获取包含 key 的 SequencedSet、包含 value 的 SequencedCollection、包含 entry键值对 的 SequencedSet以及获取集合的反向视图的方法。
interface SequencedMapK,V extends MapK,V {// New MethodsSequencedMapK,V reversed();SequencedSetK sequencedKeySet();SequencedCollectionV sequencedValues();SequencedSetEntryK,V sequencedEntrySet();V putFirst(K, V);V putLast(K, V);// Promoted Methods from NavigableMapK, VEntryK, V firstEntry();EntryK, V lastEntry();EntryK, V pollFirstEntry();EntryK, V pollLastEntry();
}SortedMap 和LinkedHashMap 实现了SequencedMap 接口。
这里以 LinkedHashMap 为例演示一下实际使用效果
LinkedHashMapInteger, String map new LinkedHashMap();map.put(1, One);
map.put(2, Two);
map.put(3, Three);map.firstEntry(); //1One
map.lastEntry(); //3ThreeSystem.out.println(map); //{1One, 2Two, 3Three}Map.EntryInteger, String first map.pollFirstEntry(); //1One
Map.EntryInteger, String last map.pollLastEntry(); //3ThreeSystem.out.println(map); //{2Two}map.putFirst(1, One); //{1One, 2Two}
map.putLast(3, Three); //{1One, 2Two, 3Three}System.out.println(map); //{1One, 2Two, 3Three}
System.out.println(map.reversed()); //{3Three, 2Two, 1One}JEP 439分代 ZGC
JDK21 中对 ZGC 进行了功能扩展增加了分代 GC 功能。不过默认是关闭的需要通过配置打开
// 启用分代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记录模式
记录模式在 Java 19 进行了第一次预览 由 JEP 405 提出。JDK 20 中是第二次预览由 JEP 432 提出。最终记录模式在 JDK21 顺利转正。
Java 20 新特性概览已经详细介绍过记录模式这里就不重复了。
JEP 441switch 的模式匹配
增强 Java 中的 switch 表达式和语句允许在 case 标签中使用模式。当模式匹配时执行 case 标签对应的代码。
在下面的代码中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();};
}JEP 442: 外部函数和内存 API第三次预览
Java 程序可以通过该 API 与 Java 运行时之外的代码和数据进行互操作。通过高效地调用外部函数即 JVM 之外的代码和安全地访问外部内存即不受 JVM 管理的内存该 API 使 Java 程序能够调用本机库并处理本机数据而不会像 JNI 那样危险和脆弱。
外部函数和内存 API 在 Java 17 中进行了第一轮孵化由 JEP 412 提出。Java 18 中进行了第二次孵化由JEP 419 提出。Java 19 中是第一次预览由 JEP 424 提出。JDK 20 中是第二次预览由 JEP 434 提出。JDK 21 中是第三次预览由 JEP 442 提出。
在 Java 19 新特性概览 中我有详细介绍到外部函数和内存 API这里就不再做额外的介绍了。
JEP 443未命名模式和变量预览
未命名模式和变量使得我们可以使用下划线 _ 表示未命名的变量以及模式匹配时不使用的组件旨在提高代码的可读性和可维护性。
未命名变量的典型场景是 try-with-resources 语句、 catch 子句中的异常变量和for循环。当变量不需要使用的时候就可以使用下划线 _代替这样清晰标识未被使用的变量。
try (var _ ScopedContext.acquire()) {// No use of acquired resource
}
try { ... }
catch (Exception _) { ... }
catch (Throwable _) { ... }for (int i 0, _ runOnce(); i arr.length; i) {...
}未命名模式是一个无条件的模式并不绑定任何值。未命名模式变量出现在类型模式中。
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虚拟线程
虚拟线程是一项重量级的更新一定一定要重视
虚拟线程在 Java 19 中进行了第一次预览由JEP 425提出。JDK 20 中是第二次预览。最终虚拟线程在 JDK21 顺利转正。
Java 20 新特性概览已经详细介绍过虚拟线程这里就不重复了。
JEP 445未命名类和实例 main 方法 预览
这个特性主要简化了 main 方法的的声明。对于 Java 初学者来说这个 main 方法的声明引入了太多的 Java 语法概念不利于初学者快速上手。
没有使用该特性之前定义一个 main 方法
public class HelloWorld {public static void main(String[] args) {System.out.println(Hello, World!);}
}使用该新特性之后定义一个 main 方法
class HelloWorld {void main() {System.out.println(Hello, World!);}
}进一步精简(未命名的类允许我们不定义类名)
void main() {System.out.println(Hello, World!);
}