Java19的主要新特性总结

目录

Java19的主要新特性总结

概述

变动说明

重要变更和信息

下载地址

Java19新特性总结

1、JEP 427: Switch 的模式匹配(第三次预览)

功能进化

Switch 模式匹配

类型标签

null标签

守卫标签

2、JEP 405:Record模式(预览)

3、JEP 422:Linux/RISC-V移植

4、JEP 424:外部函数和内存 API(预览)

功能进化

5、JEP 425:虚拟线程(预览)

6、JEP 426:向量API(第四次孵化)

功能进化

7、JEP 428:结构化并发(孵化特性)

8、移除的APIs、工具、容器


概述

JDK 19 于 2022 年 9 月 20 日正式发布。

JEP(Java Enhancement Proposal)Java增强提案

CSR(Compatibility & Specification Review) 兼容性和规范审查

变动说明

官网:

Java Platform, Standard Edition Java Language Updates, Release 19

JDK 19 Release Notes, Important Changes, and Information

JDK 19

https://blogs.oracle.com/java/post/the-arrival-of-java-19

更多参考:

JDK 19 Documentation - Home 更多版本:Java Platform, Standard Edition Documentation - Releases

Java Platform, Standard Edition Oracle JDK Migration Guide, Release 19

重要变更和信息

JDK 19 包含 7 个 新特性 ,分别为:

而其中与开发过程中直接相关的特性主要包括:JEP 405(Record模式)、JEP 427(Switch 表达式的模式匹配)等。

下载地址

你可以从这个链接下载Oracle JDK版本,更多版本下载

也可以从这个链接下载生产就绪的OpenJDK版本。文件为压缩包,解压并设置环境变量就可以使用。

Java19新特性总结

1、JEP 427: Switch 的模式匹配(第三次预览)

JEP 427specification/language

这仍然是一个预览特性

功能进化

switch表达式的功能进化

java版本特性类型JEP特性
Java 5首次引入,仅支持整型数据类型(如 byte, short, char, 和 int)及枚举类型
Java 7支持 String 类型
Java 12预览特性JEP 325支持Switch表达式(箭头函数)
Java 13预览特性JEP 354加入 yield 语句来替代 break 语句,用于从 switch 表达式返回值
Java 14正式特性JEP 361前2个版本的新特性转为正式特性
Java 17预览特性JEP 406引入模式匹配的Switch表达式作为预览特性
Java 18第二次预览JEP 420调整优化
Java 19第三次预览JEP 427调整优化

在 Java 16 中, JEP 394instanceof的模式匹配发布为正式属性。虽然可以不需要强制转换了,但是仍然需要大量的 if...else。而 Switch 表达式虽然简化了if...else,但是它无法像instanceof一样不需要强制转换。为了解决这个痛点,Java 17引入模式匹配的Switch表达式特性 ,目前该特性为预览特性。

该特性扩展了 switch 表达式和语句,允许它们使用模式匹配,这就意味着我们可以在 switch 的 case 标签中使用模式,如类型模式,使得代码更加灵活和表达性更强。而且也无需进行显式的类型转换了。例如,可以使用 case Integer i 这样的语法来匹配并自动转换类型。

但是,不知道小伙伴们注意没有,Switch 表达式只有一种类型,比如:我有一个诗人类(Poet),它有3个实现类:唐朝诗人(TangPoet)、宋朝诗人(SongPoet)、汉朝诗人(HanPoet),我要根据诗人的类型进行不同处理 :

 Poet poet = ... // 诗人
 ​
 switch (poet.getClass().getName()) {
     case "my.poet.TangPoet":
         TangPoet tp = (TangPoet) obj;
         // 处理唐朝诗人
         break;
     case "my.poet.SongPoet":
         SongPoet sp = (SongPoet) obj;
         // 处理宋朝诗人
         break;
     case "my.poet.HanPoet":
         HanPoet hp = (HanPoet) obj;
         // 处理汉朝诗人
         break;
     // 其他类型
 }

这个强转显然比较麻烦。所以,参考Java 17中,参考instanceof的模式匹配,为switch表达式引入了模式匹配功能作为预览特性。

Switch 模式匹配

在 Java 17 中,switch 表达式允许使用模式匹配来处理对象类型,这样就可以直接在 switch 语句中检查和转换类型,而不需要额外的 if...else 结构和显式类型转换。

case后面可以跟的标签主要有:

  • 类型标签

  • null标签

  • 守卫标签

  • enum或常量值

类型标签

允许在 switch 语句的 case 分支中直接匹配对象的类型。例如,case String s 允许你在该分支中直接作为字符串类型的 s 来使用,避免了显式的类型检查和强制类型转换。

举个例子:

 @Test
 public void switchTest() {
     // 不是用switch根据类型判断
     Object[] objects = { "Hello", "Java", "17", 666, 0.618 };
     for (Object obj : objects) {
         if (obj instanceof Integer v) {
             System.out.printf("为整型 :%s %n", v);
         } else if (obj instanceof Float v) {
             System.out.printf("为Float:%s %n", v);
         } else if (obj instanceof Double v) {
             System.out.printf("为Double:%s %n", v);
         } else if (obj instanceof String v) {
             System.out.printf("为字符串:%s %n", v);
         } else {
             System.out.printf("其他类型:%s %n", obj);
         }
     }
 }

我们用 Switch 表达式来改造下:

 @Test
 public void switchTest() {
     Object[] objects = { "Hello", 123, "World", "Java", 3.14, "skjava" };
     for (Object obj: objects) {
         switch (obj) {
             case Integer v -> System.out.println("为整数型:" + v);
             case Float v -> System.out.println("为浮点型:" + v);
             case Double v -> System.out.println("为双精度浮点数:" + v);
             case String v -> System.out.println("为字符串:" + v);
             default -> System.out.println("其他类型:" + obj);
         }
     }
 }

相比上面的 if...else 简洁了很多。同时在 Java 17之前,Switch选择器表达式只支持特定类型,即基本整型数据类型byteshortcharint;对应的装箱形式ByteShortCharacterIntegerString类;枚举类型。现在有了类型模式,Switch 表达式可以是任何类型啦。

null标签

switch允许任何引用类型的选择器表达式,那么我们需要留意null的情况,在Java17之前,向switch语句传递一个null值,会抛出一个NullPointerException,现在可以通过类型模式,将 null 检查作为一个单独的case标签来处理,如下:

 @Test
 public void switchTest() {
     Object[] objects = { "Hello", "Java", "17", 142857, 0.618 };
     for (Object obj: objects) {
         switch (obj) {
             case Integer v -> System.out.println("为整数型:" + v);
             case Float v -> System.out.println("为浮点型:" + v);
             case Double v -> System.out.println("为双精度浮点数:" + v);
             case String v -> System.out.println("为字符串:" + v);
             case null -> System.out.println("为空值");
             default -> System.out.println("其他类型:" + obj);
         }
     }
 }

case null 可以直接匹配值为 null 的情况。

守卫标签

与匹配常量值的case标签不同,模式case标签可以对应多个变量值。这通常会导致switch规则右侧出现条件语句。

根据字符串长度判断诗句是五言绝句还是七言绝句,代码如下:

 @Test
 public void switchCaseCaseTest() {
     String[] poems = { "千山鸟飞绝", "春城无处不飞花", "红豆生南国", "二月春风似剪刀","念奴娇" };
     for (String poem : poems) {
         switch (poem) {
             case null -> System.out.println("为空值");
             case String s -> {
                 if (s.length() == 5)
                     System.out.printf("五言绝句:%s%n", s);
                 else if (s.length() == 7)
                     System.out.printf("七言绝句:%s%n", s);
                 else
                     System.out.printf("不知道是啥:%s%n", s);
             }
         }
     }
 }

这里的问题是,使用单一模式(即类型)来区分case就只能判断一种情况。我们只能在模式匹配中再通过if……else判断来区分不同的情况,来对一个模式的细化。这时,我们可以是使用switch中的when子句指定模式case标签的条件,例如,case String s when if (s.length() == 5)。表示当类型为String并且字符串长度为5的时候,我们将这种case标签称为守卫case标签,将布尔表达式称为保护。

 @Test
 public void switchCaseCaseTest() {
     String[] poems = { "千山鸟飞绝", "春城无处不飞花", "红豆生南国", "二月春风似剪刀","念奴娇" };
     for (String poem : poems) {
         switch (poem) {
             case null -> System.out.println("为空值");
             case String s when s.length() == 5 -> System.out.printf("五言绝句:%s%n", s);
             case String s when s.length() == 7 -> System.out.printf("七言绝句:%s%n", s);
             case String s -> System.out.printf("不知道是啥:%s%n", s); //剩余情况,仍然走这个
         }
     }
 }

使用守卫标签,我们可以编写更灵活和表达性强的代码。

2、JEP 405:Record模式(预览)

JEP 405

Java 14 引入预览特性 Record类提供一种简洁的语法来声明数据载体的不可变对象,主要是为了解决长期以来在 Java 中定义纯数据载体类时,代码过于繁琐的问题。在 Java 16 中转为正式特性。

模式匹配最初是用在instanceof上,在 Java 14 作为预览特性引入的,为了解决 instanceof 在做类型匹配时需要进行强制类型转换而导致的代码冗余。

Java 19 引入 Record 模式作为预览特性,它允许在instanceof操作中使用记录模式,直接解构和匹配记录中的字段。

比如有一个记录Record Point(int x, int y),可以使用 Record 模式直接检查和提取 xy 值:

 if (obj instanceof Point(int x, int y)) {
   System.out.println(x+y);
 }

可以看出,类型判断、类型转换、Record变量赋值一气呵成,极大地简化了代码结构。

该特性使Java 模式匹配能力得到进一步扩展。

3、JEP 422:Linux/RISC-V移植

JEP 422

JDK移植到Linux/RISC-VRISC-V是一个基于精简指令集(RISC)原则的开源指令集架构(ISA)。

4、JEP 424:外部函数和内存 API(预览)

JEP 424 (core-libs)

这是一个预览特性。

功能进化
java版本特性类型JEP特性
Java 14孵化特性JEP 370引入了外部内存访问 API作为孵化特性
Java 15第二次孵化JEP 383优化外部内存访问 API
Java 16孵化特性JEP 389引入了外部链接器 API
Java 16第三次孵化JEP 393功能优化
Java 17孵化特性JEP 412引入了外部函数和内存 API
Java 18第二次孵化JEP 419改进
Java 19预览特性JEP 424改进

外部函数和内存 API 是在 Java 17 中作为孵化器引入的,它提供对本机代码的静态类型的纯Java访问,其主要目的是改善 Java 与本地代码(如 C 或 C++)的互操作性。此APIForeign-Memory API(JEP 393)一起,将大大简化绑定到本机库的错误处理过程。

一般Java想要调用本地代码需要使用Java Native Interface (JNI),但是JNI操作比较复杂而且性能有限。

外部函数和内存API提供了一套更简洁的API,用于调用本地函数和处理本地内存,降低了复杂性,而且还设计了更多的安全保护措施,降低了内存泄露和应用崩溃的风险。

主要是通过两个组件实现的:

  1. Foreign Function Interface (FFI): 允许 Java 代码直接调用非 Java 代码,比如 C/C++ 代码。

  2. Foreign Memory Access API:提供了一种安全的方法来访问不受JVM管理的内存。

5、JEP 425:虚拟线程(预览)

JEP 425core-libs/java.lang

将虚拟线程引入Java平台。虚拟线程是轻量级线程,可以显著减少编写、维护和观察高吞吐量并发应用程序的工作量。

虚拟线程是一种轻量级的线程,也就是我们俗称的协程。它的资源分配和调度由VM实现,而不是操作系统。虚拟线程的主要特点包括:

  1. 轻量级:与传统线程相比,它更轻量,创建和销毁的成本较低。

  2. 简化并发编程:由于不受操作系统线程数量的限制,我们可以为每个独立的任务创建一个虚拟线程,简化并发编程模型。

6、JEP 426:向量API(第四次孵化)

JEP 426 (core-libs)

功能进化
java版本特性类型JEP特性
Java 16第一次孵化JEP 338提供一个平台无关的方式来表达向量计算,能够充分利用现代处理器上的向量硬件指令。
Java 17第二次孵化JEP 414改进
Java 18第三次孵化JEP 417进一步增强
Java 19第四次孵化JEP 426进一步增强

向量 API 是在 Java 16 中作为孵化特性引入的。

引入API来表示向量计算,这些向量计算在运行时可靠地编译为支持的CPU架构上的最佳向量指令,从而实现优于等效标量计算的性能。Java 18 对向量 API 进行了进一步的改进和增强,以更好地利用硬件功能,提高 Java 在数值计算和机器学习等领域的性能。

7、JEP 428:结构化并发(孵化特性)

JEP 428

这是一个孵化特性。

通过引入用于结构化并发的API来简化多线程编程。结构化并发将在不同线程中运行的多个任务视为一个工作单元,从而简化错误处理和消除,提高可靠性,并增强可观察性。

8、移除的APIs、工具、容器

参考:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值