0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

一文了解Java 21的新功能

jf_ro2CN3Fa 来源:medium.com 2023-12-21 16:19 次阅读

来源:medium.com

JDK 21 于 2023 年 9 月 19 日发布,是继之前的 LTS 版本 JDK 17 之后最新的长期支持 (LTS) 版本。在本文中,我们将探讨 JDK 21 新引入的功能。

以下是 JDK 21 的新功能列表:

虚拟线程

序列集合

记录模式

字符串模板(预览)

未命名模式和变量(预览)

未命名类和实例主要方法(预览)

作用域值(预览)

结构化并发(预览)

1 虚拟线程

Java 代码的角度来看,虚拟线程感觉就像普通线程,但它们没有 1:1 映射到操作系统/平台线程。它是从虚拟线程到载体线程进而到操作系统线程的M:N映射。

有一个所谓的载体线程池,虚拟线程临时映射(“安装”)到该线程池上。一旦虚拟线程遇到阻塞操作,虚拟线程就会从载体线程中移除(“卸载”),并且载体线程可以执行另一个虚拟线程(新的或之前被阻塞的虚拟线程)。

载体线程池是ForkJoinPool

d9d291e0-9740-11ee-8b88-92fbcf53809c.png

虚拟线程的一些优点:

提高应用程序吞吐量

提高应用程序可用性

减少内存消耗

创建虚拟线程

要创建虚拟线程,我们可以使用 Thread.ofVirtual() 工厂方法并传递可运行对象。

Thread.ofVirtual().start(Runnable);

Thread.ofVirtual().unstarted(Runnable);

如果你想让虚拟线程立即启动,你可以使用start() 方法,它会立即执行传递给它的Runnable start()。

如果不希望虚拟线程立即启动,可以使用该unstarted()方法。

创建使用虚拟线程的ExecutorService

我们只需要替换newFixedThreadPool为newVirtualThreadPerTaskExecutor

importjava.util.concurrent.ExecutorService;
importjava.util.concurrent.Executors;

publicclassVirtualThreadExample{

publicstaticvoidmain(String[]args){
ExecutorServiceexecutor=Executors.newVirtualThreadPerTaskExecutor();

executor.submit(()->{
System.out.println(Thread.currentThread().getName())
});

executor.shutdown();
}
}

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

项目地址:https://github.com/YunaiV/ruoyi-vue-pro

视频教程:https://doc.iocoder.cn/video/

2 顺序集合

顺序集合为我们提供了defined encounter order(是一种所见即所得的顺序,含义是从队列中取出元素的顺序既是你存放该元素时候的顺序),用于访问第一个和最后一个元素并以相反的顺序迭代。

这意味着我们可以在集合的两端添加、检索或删除元素。

d9e8a2b4-9740-11ee-8b88-92fbcf53809c.png

publicinterfaceSequencedCollectionextendsCollection{
defaultvoidaddFirst(Ee){...}
defaultvoidaddLast(Ee){...}
defaultEgetFirst(){...}
defaultEgetLast(){...}
defaultEremoveFirst(){...}
defaultEremoveLast(){...}
SequencedCollectionreversed();
}

正如我们所看到的,除了reverse()之外的所有方法都是默认方法并提供默认实现。

这意味着现有的集合类(例如 ArrayList 和 LinkedList)都可以实现此接口,而无需更改其代码。

ArrayListlist=newArrayList<>();
list.add(1);//[1]
list.addFirst(0);//[0,1]
list.addLast(2);//[0,1,2]
list.getFirst();//0
list.getLast();//2
list.reversed();//[2,1,0]

SequencedSet

SequencedSet 接口对于具有有序元素的 Set 非常有用,特别是当您必须执行某些操作(例如检索或删除第一个或最后一个索引处的元素)时。它还提供了一种反转元素的方法。

您还需要知道两个 SequencedSet 对象的比较与其他类型的 Set 相同,不依赖于元素顺序。

interfaceSequencedSetextendsSet,SequencedCollection{
SequencedSetreversed();
}

LinkedHashSet 是 Set 的一个实现,它实现了 SequencedSet 接口。

因此,您可以使用 LinkedHashSet 来创建 SequencedSet。

Set 的其他实现(例如 HashSet 和 TreeSet)未实现该接口。

让我们探索一些示例来演示如何访问第一个和最后一个元素,以及如何使用反向函数:

SequencedSetvalues=newLinkedHashSet<>();
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]

values.removeFirst();
System.out.println(values);//[zero,two,three]

SequencedSetreversedSet=values.reversed();
System.out.println(reversedSet);//[three,two,zero]

booleanisEqual=values.equals(reversedSet);
System.out.println(isEqual);//true
System.out.println(values.hashCode());//612888
System.out.println(reversedSet.hashCode());//612888
System.out.println(values.hashCode()==reversedSet.hashCode());//true

SequencedMap

如果要使用 SequencedMap 中定义的新方法,则需要使用 Map 实现,例如 LinkedHashMap 或实现 SortedMap 的 Map。

HashMap 不利用 Sequenced Collections,因为它没有定义 defined encounter order(是一种所见即所得的顺序,含义是从队列中取出元素的顺序既是你存放该元素时候的顺序)。

interfaceSequencedMapextendsMap{
SequencedMapreversed();
SequencedSetsequencedKeySet();
SequencedCollectionsequencedValues();
SequencedSet>sequencedEntrySet();
VputFirst(K,V);
VputLast(K,V);
EntryfirstEntry();
EntrylastEntry();
EntrypollFirstEntry();
EntrypollLastEntry();
}

在下面的示例中,正如您所看到的,我们可以通过firstEntry()和lastEntry()方法访问第一个和最后一个元素。

pollFirstEntry()方法将删除并返回第一个键值元素,如果映射为空,则返回 null。

此外,调用reverse()只会比较元素,而不依赖于它们的顺序。

SequencedMapmyMap=newLinkedHashMap<>();
myMap.put("one",1);
myMap.put("two",2);
System.out.println(myMap);//{one=1,two=2}

EntryfirstEntry=myMap.firstEntry();
System.out.println(firstEntry);//one=1

EntrylastEntry=myMap.lastEntry();
System.out.println(lastEntry);//two=2

myMap.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}

EntrypolledFirstEntry=myMap.pollFirstEntry();
System.out.println(polledFirstEntry);//one=-1
System.out.println(myMap);//{zero=0,two=2}

SequencedMapreversedMap=myMap.reversed();
System.out.println(reversedMap);//{two=2,zero=0}

booleanisEqual=myMap.equals(reversedMap);
System.out.println(isEqual);//true
System.out.println(myMap.hashCode());//692224
System.out.println(reversedMap.hashCode());//692224
System.out.println(myMap.hashCode()==reversedMap.hashCode());//true

3 字符串模板

这是预览功能,默认禁用,我们需要使用

--enable-preview启用字符串模板。

首先,在深入探讨字符串模板之前,我将探讨一些用于组合字符串的技术。

+(加号)运算符: 最大的缺点是每次使用 + 运算符时都会创建一个新字符串。

StringBuffer 和 StringBuilder: StringBuffer 是线程安全的,而 StringBuilder 是在 Java 5 中添加的,性能更高,但不是线程安全的替代方案。

它们的主要缺点是冗长,尤其是对于更简单的字符串:

vargreeting=newStringBuilder()
.append("Hello,welcome")
.append(name)
.toString();

String::format 和 String::formatter: 它们允许可重用模板,但它们要求我们指定格式并以正确的顺序提供变量。

varformat="Goodmorning%s,It'sabeautifulday!";
vartext=String.format(format,name);
//Java15+
vartext=format.formatter(name);

尽管我们节省了字符串分配的数量,但现在 JVM 必须解析/验证模板字符串。

java.text.MessageFormat: 与String格式相同,但更详细

varformat=newMessageFormat("Goodmorning{0},It'sabeautifulday!");
vargreeting=format.format(name);

现在我们有字符串模板来拯救

它简单、简洁,处理字符串的新方法称为模板表达式。它们可以执行插值,还为我们提供了组合字符串的灵活性,并将结构化文本转换为任何对象,而不仅仅是字符串。

模板表达式由三个组成部分组成:

模板处理器:Java 提供了两种用于执行字符串插值的模板处理器:STR 和 FMT

包含包装表达式的模板,如 {name}

点 (.) 字符

以下是一些关于如何将字符串模板与模板处理器一起使用的示例:

packagecom.mina.stringtemplates;

importstaticjava.util.FormatProcessor.FMT;

importjava.time.LocalDate;
importjava.time.format.DateTimeFormatter;

publicclassStringTemplateExamples{

publicstaticStringgreeting(StringfirstName,StringlastName){
returnSTR."Hello!Goodmorning{firstName}{lastName}";
}

publicstaticStringmultiplyWithArithmeticExpressions(inta,intb){
returnSTR."{a}times{b}={a*b}";
}

publicstaticStringmultiplyWithJavaExpression(inta,intb){
returnSTR."{a}times{b}={Math.multiplyExact(a,b)}";
}

//multiplicationwithfloatingpointnumbersroundedtotwodecimalplacesusingtheFMTtemplateprocessor
publicstaticStringmultiplyFloatingNumbers(doublea,doubleb){
returnFMT."%.2f{a}times%.2f{b}=%.2f{a*b}";
}

publicstaticStringgetErrorResponse(inthttpStatus,StringerrorMessage){
returnSTR."""
{
"httpStatus":{httpStatus},
"errorMessage":"{errorMessage}"
}""";
}

publicstaticStringgetCurrentDate(){
returnSTR."Today'sdate:{
LocalDate.now().format(
DateTimeFormatter.ofPattern("yyyy-MM-dd")
)}";
}
}

4 记录模式

记录模式匹配是一种在单个步骤中匹配记录类型并访问其组件的方法。

我们用它来测试一个值是否是记录类类型的实例,如果是,则对其组件值执行模式匹配。

下面的示例测试是否是具有记录模式transaction的记录实例TransactionTransaction(String type, double amount)

packagecom.mina.recordpattern;

publicclassRecordPatternExample{

//I'musing"_"forreadabilityhere,thiswon'tcompile
publicstaticStringgetTransactionType(Transactiontransaction){
returnswitch(transaction){
casenull->thrownewIllegalArgumentException("Transactioncannotbenull.");
caseTransaction(Stringtype,doubleamount)whentype.equals("Deposit")&&amount>0->"Deposit";
caseTransaction(Stringtype,_)whentype.equals("Withdrawal")->"Withdrawal";
default->"Unknowntransactiontype";
};
}

recordTransaction(Stringtype,doubleamount){

}
}

如果事务为空,会发生什么?你是对的——抛出了一个空指针异常。这也是Java 21中的情况,但是现在我们可以通过写case null->来显式地使用null case,这样可以避免NullPointerException。

保护模式:也可以保护特定情况。例如,我们使用when关键字来检查相等性。

5 switch 模式匹配

switch模式匹配在 Java 17 中作为预览功能引入,并在 Java 21 中永久保留。

语句switch将控制转移到多个语句或表达式之一,具体取决于其选择器表达式的值(可以是任何类型),并且case标签可以具有模式。

它检查其选择器表达式是否与模式匹配,与测试其选择器表达式是否完全等于常量相比,这更具可读性和灵活性。

packagecom.mina.switchpatternmatching;

importcom.mina.switchpatternmatching.SwitchPatternMatchingExample.Transaction.Deposit;
importcom.mina.switchpatternmatching.SwitchPatternMatchingExample.Transaction.Withdrawal;

publicclassSwitchPatternMatchingExample{

publicstaticStringgetTransactionType(Transactiontransaction){
returnswitch(transaction){
casenull:
thrownewIllegalArgumentException("Transactioncan'tbenull.");
caseDepositdepositwhendeposit.getAmount()>0://Guardedpatternwithwhenclause
yield"Deposit";
caseWithdrawalwithdrawal:
yield"Withdrawal";
default:
yield"Unknowntransactiontype";
};
}

sealedclassTransactionpermitsDeposit,Withdrawal{

privatedoubleamount;

publicTransaction(doubleamount){
this.amount=amount;
}

publicdoublegetAmount(){
returnamount;
}


finalclassWithdrawalextendsTransaction{

publicWithdrawal(doubleamount){
super(amount);
}
}

finalclassDepositextendsTransaction{

publicDeposit(doubleamount){
super(amount);
}
}
}
}

希望这篇文章可以帮助您更好地了解 Java 21 的新功能!


审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • JAVA
    +关注

    关注

    19

    文章

    2904

    浏览量

    102995
  • 字符串
    +关注

    关注

    1

    文章

    552

    浏览量

    20130
  • 代码
    +关注

    关注

    30

    文章

    4556

    浏览量

    66784
  • 线程
    +关注

    关注

    0

    文章

    489

    浏览量

    19495

原文标题:Java 21 新特性的实践,确实很丝滑!

文章出处:【微信号:芋道源码,微信公众号:芋道源码】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    PowerDesigner 10.0的新功能

    PowerDesigner 10.0的新功能Available February 9, 2004Business Process Simulation using
    发表于 06-27 17:01

    allegro 16.6 部分新功能 介绍

    本帖最后由 eric0921 于 2012-8-27 21:24 编辑 allegro 16.6部分新功能介绍
    发表于 08-27 21:23

    Cadence_16.5的新功能

    ALLEGRO16.6的新功能,希望对你有用。
    发表于 11-15 10:19

    Cadence Allegro 17.4新功能

    Cadence Allegro 17.4新功能
    发表于 10-28 21:19

    Altium Designer 20 新功能官方直播

    ,Altium大中华区技术经理将为大家带来Altium Designer 20的官方直播!现场、讲解演示新版本的全新功能及增强功能,还等什么,快复制链接报名吧!报名链接:https
    发表于 12-27 15:06

    请问Python3.9的新功能是什么?

    3.9 的完整版本。些最新功能令人难以置信,看到Python 3.9 在发布后会被使用。我们将看到以下新功能,即字典联合运算符、类型提示、两种新的字符串方法、新的Python解析器 。下面让我们首先看
    发表于 09-02 18:55

    AWTK Designer 1.0.2有哪些新功能

    为不断提升用户体验,本次Designer 1.0.2增加了自定义控件和插件管理以及其他许多新功能,并对现有功能进行了优化,让我们起来看看这些很酷的新功能吧!
    发表于 03-04 08:27

    请教下智能口罩有哪些新功能

    请教下智能口罩有哪些新功能
    发表于 06-26 06:53

    了解LVGL的学习路线

    “本文大部分内容来自LVGL官方文档,手翻版,如有错误欢迎指正。”系列文章目录、LVGL系列(了解LVGL的学习路线轻松
    发表于 12-07 12:55

    如何更新USB设备库v2.10.0档来解释新功能呢?

    我注意到 CubeH7 v1.10.0 附带 USB 设备库 v2.10.0,它支持新的类驱动程序和复合设备。但是我找不到任何文档或示例与这些新功能相对应。ST,你能更新USB设备库文档来解释新功能吗?
    发表于 12-26 11:28

    21天学通JAVA2_袁国忠译

    21天学通Java2》包括4周的课程。第一周介绍Java语言的基本知识,包括数据类型、变量、表达式、对象、数组、条件语句、循环、类、接口、包异常和线程等;第二周介绍Java类库,包括
    发表于 12-06 10:38 0次下载
    <b class='flag-5'>21</b>天学通<b class='flag-5'>JAVA</b>2_袁国忠译

    Java学习路线教程之Java新手必须学习那21个技术点详细资料说明

    Java新手必学的21个技术点 以下为大家盘点作为Java新手必学的21个技术点,希望能够对想要学习编程,学习JAVA的人有些帮助! JN
    发表于 12-19 15:23 19次下载

    微软开始测试 21H1 的功能体验包功能 无需大版本更新即可体验

    Win10 21H1 是一个小更新,它将在 2021 年上半年(5 月至 6 月)到来。21H1 几乎完全没有添加任何新功能,似乎仅在安全性和 “质量”方面有所改进,包括 Windows Hello
    的头像 发表于 02-24 14:29 1782次阅读

    LTspice IV有什么新功能

    LTspice IV有什么新功能
    发表于 05-27 12:52 2次下载
    LTspice IV有什么<b class='flag-5'>新功能</b>?

    Java21版本的使用

      如果你是一位苦逼的 Java 程序员,那么当你看到这张图的时候也许震惊的会跳起来! 但是我最大的感受是: 卧槽,怎么就Java 21了?!我还在用Java 8 呢! 实际上,从
    的头像 发表于 06-19 09:42 1417次阅读
    <b class='flag-5'>Java21</b>版本的使用