文章目录
Java19新特性
JDK 19 定于 2022 年 9 月 20 日正式发布以供生产使用,非长期支持版本。不过,JDK 19 中有一些比较重要的新特性值得关注。
官方文档:OpenJDK Java 19 文档
Java各个版本的文档入口:Java平台,标准版文档
Java各个版本下载:https://jdk.java.net/archive/
JDK 19 只有 7 个新特性:
- JEP 405: Record Patterns(记录模式)(预览)
- JEP 422: JDK移植到Linux/RISC-V Port
- JEP 424: Foreign Function & Memory API(外部函数和内存 API)(预览)
- JEP 425: Virtual Threads(虚拟线程)(预览)
- JEP 426: Vector(向量)API(第四次孵化)
- JEP 427: Pattern Matching for switch(switch 模式匹配)(第三次预览)
- JEP 428: Structured Concurrency(结构化并发)(孵化)
JEP 405: Record Patterns(记录模式)(预览)
Record 是 Java 14 引入的,它主要目的是提供一种简洁的语法来声明类似数据的小型不可变对象,主要是为了解决长期以来在 Java 中定义纯数据载体类时,代码过于繁琐的问题。它的本质上是一个不可变的、透明的数据载体对象,我们可以理解它是一种特殊类型的 Java 类。定义 Record 方法如下:
public record User(String name,Integer age) {
}
Record 会自带 getters、equals()、hashCode() 和 toString() 方法,无需我们手写。
但是我们在使用类型匹配时仍然需要强制转换下,如下:
public void recordTest(Object obj) {
if (obj instanceof User) {
User user = (User) obj;
String name = user.name();
Integer age = user.age();
}
}
这种做法无疑是繁琐的。还记得 Java 14 引入的模式匹配的 instanceof吗?它允许在 instanceof 操作符的条件判断中直接定义一个变量,如果对象是指定的类型,这个变量会被初始化为被检查的对象,可以立即使用,而无需额外的类型转换。这不就解决了我们的问题吗?
Java 19 引入模式匹配(Record Patterns),它允许我们通过模式匹配直接提取组件,而不需要先进行强制类型转换后再提取。它需要与 instanceof 或 switch 模式匹配一同使用。
我们先看 instanceof,改造如下:
public void recordTest(Object obj) {
if (obj instanceof User user) {
String name = user.name();
Integer age = user.age();
}
}
那在 Switch 表达式中呢,如下:
public void recordTest(Object obj) {
switch (obj) {
case null -> throw new NullPointerException("不能为空");
case User user -> System.out.println("name:" + user.name() + "--age:" + user.age());
default -> obj.toString();
}
}
我们还可以将 User 的属性直接提取出来,如下:
public void recordTest(Object obj) {
switch (obj) {
case null -> throw new NullPointerException("不能为空");
case User(String name,Integer age) -> System.out.println("name:" + name + "--age:" + age);
default -> obj.toString();
}
}
我们再衍生下,case User(String name,Integer age) 一定要这么写吗?我们都知道了它是 User 类型了,他的属性类型是不是就是固定的?还记得 Java 10 引入的局部变量类型推断么?我们可不可以用 var 来代替?其实是可以的:
public void recordTest(Object obj) {
switch (obj) {
case null -> throw new NullPointerException("不能为空");
case User(var name,var age) -> System.out.println("name:" + name + "--age:" + age);
default -> obj.toString();
}
}
所以,在声明模式变量时,我们并不需要显式地指定类型,用 var 也行,具体的类型由编译器自动推断。
JEP 422: JDK移植到Linux/RISC-V Port
这个改动点的重点不是移植工作本身,它几乎已经完成,而是将端口集成到JDK主线存储库中。
JDK主线和RISC-V端口项目之间的当前差异可以通过以下方式获得:
$ git clone https://github.com/openjdk/riscv-port riscv-port
$ cd riscv-port
$ git diff master…riscv-port
JEP 424: Foreign Function & Memory API(外部函数和内存 API)(预览)
此功能已经过多次孵化。在Java 19中进行第一次预览。
Java 程序可以通过该 API 与 Java 运行时之外的代码和数据进行互操作。通过高效地调用外部函数(即 JVM 之外的代码)和安全地访问外部内存(即不受 JVM 管理的内存),该 API 使 Java 程序能够调用本机库并处理本机数据,而不会像 JNI 那样危险和脆弱。
在没有外部函数和内存 API 之前:
- Java 通过
sun.misc.Unsafe提供一些执行低级别、不安全操作的方法(如直接访问系统内存资源、自主管理内存资源等),Unsafe类让 Java 语言拥有了类似 C 语言指针一样操作内存空间的能力的同时,也增加了 Java 语言的不安全性,不正确使用Unsafe类会使得程序出错的概率变大。 - Java 1.1 就已通过 Java 原生接口(JNI)支持了原生方法调用,但并不好用。JNI 实现起来过于复杂,步骤繁琐,不受 JVM 的语言安全机制控制,影响 Java 语言的跨平台特性。并且,JNI 的性能也不行,因为 JNI 方法调用不能从许多常见的 JIT 优化(如内联)中受益。虽然JNA、JNR和JavaCPP等框架对 JNI 进行了改进,但效果还是不太理想。
引入外部函数和内存 API 就是为了解决 Java 访问外部函数和外部内存存在的一些痛点。
Foreign Functio

最低0.47元/天 解锁文章
1104

被折叠的 条评论
为什么被折叠?



