JDK22新特性及演示代码示例

0.前言

JDK 22 于 2024 年 3 月 19 日正式发布。

1.JEP 423:G1垃圾收集器的区域固定

通过在 G1 中实现区域固定来减少延迟,以便在 Java 本机接口 (JNI) 关键区域期间无需禁用垃圾收集。

不会因 JNI 关键区域而导致线程停顿。

由于 JNI 关键区域,启动垃圾收集不会产生额外的延迟。

当没有 JNI 关键区域处于活动状态时,GC 暂停时间不会回归。

当 JNI 关键区域处于活动状态时,GC 暂停时间的回归最小。

注:GC暂停回归:GC暂停时间变长。

2.JEP 447:super(…) 之前的语句(预览)

在 Java 编程语言的构造函数中,允许不引用正在创建的实例的语句出现在显式构造函数调用之前。这是预览功能。

public class JEP447Rectangle {

        private int length;

        private int width;

        public JEP447Rectangle(){

        }

        public JEP447Rectangle(int length,int width){
            this.length = length;
            this.width = width;
        }

        public int getArea(){
            return length * width;
        }
}

public class JEP447Square extends JEP447Rectangle{

    public JEP447Square(int area){
        if(area<0)throw new IllegalArgumentException();
        int length = (int)Math.sqrt(area);
        System.out.println("length:"+length);
        super(length,length);

    }

    public static void main(String[] args) {
        new JEP447Square(9);
    }
}
javac --enable-preview --source 22 -Xlint:preview JEP447Square.java

javac --enable-preview --source 22 -Xlint:preview JEP447Square.java

java --enable-preview JEP447Square

java --enable-preview JEP447Square

3.JEP 454:外部函数和内存 API

引入一个 API,Java 程序可以通过该 API 与 Java 运行时之外的代码和数据进行互操作。 通过有效地调用外部函数(即 JVM 外部的代码),并安全地访问外部内存(即不受 JVM 管理的内存),API 使 Java 程序能够调用本机库并处理本机数据,而不会出现JNI的脆弱性和危险。

import java.lang.foreign.*;
import java.lang.invoke.MethodHandle;

public class JEP454 {

    public static void main(String[] args) {
        // 1. 获取常用库的查找对象
        SymbolLookup stdlib = Linker.nativeLinker().defaultLookup();

        // 2. 获取 C 标准库中“strlen”函数的句柄
        MethodHandle strlen =
                Linker.nativeLinker()
                        .downcallHandle(
                                stdlib.find("strlen").orElseThrow(),
                                FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS));

        // 3. 获取一个受限内存区域(我们可以显式关闭的内存区域)
        try (Arena offHeap = Arena.ofConfined()) {

            // 4. 将Java字符串转换为C字符串并将其存储在堆外内存中
            MemorySegment str = offHeap.allocateFrom("coding if fun!");

            // 5. 调用外部函数
            long len = 0;
            try {
                len = (long) strlen.invoke(str);
            } catch (Throwable e) {
                e.printStackTrace();
            }
            System.out.println("len = " + len);
        }
        // 6. 堆外内存在 try-with-resources 结束时被释放
    }
}
java --enable-native-access=ALL-UNNAMED JEP454

java --enable-native-access=ALL-UNNAMED JEP454

4.JEP 456:未命名变量和模式

使用未命名变量和未命名模式增强 Java 编程语言,当需要变量声明或嵌套模式但从未使用时可以使用它们。 两者均由下划线字符 _ 表示。

import java.util.*;

public class JEP456 {

    private static void printMap(Map<String,List> map){
        Set<String> keySet = map.keySet();
        Iterator<String> iterator = keySet.iterator();
        while (iterator.hasNext()){
            String keyS = iterator.next();
            System.out.println("key:"+keyS+","+map.get(keyS));
        }
    }

    public static void main(String[] args) {
        try {
            String string = "codingisfun";
            int number = Integer.parseInt(string);
        } catch (NumberFormatException _) {
            System.err.println("It is not a number");
        }

        Map<String,List> map = new HashMap<>();

        System.out.println("============before=============");
        printMap(map);

        String key = "coding";
        String value = "fun";
        map.computeIfAbsent(key, _ -> new ArrayList<>()).add(value);

        System.out.println("============after=============");
        printMap(map);

    }
}
javac -Xlint:unchecked JEP456.java

javac -Xlint:unchecked JEP456.java

java JEP456

java JEP456

4.JEP 457:类文件 API(预览版)

提供用于解析、生成和转换 Java 类文件的标准 API。这是一个预览 API。
Java 类文件 API 是用于读取和写入 .class 文件(即编译后的 Java 字节码)的接口。 新的 API 旨在取代 JDK 中大量使用的字节码操作框架 ASM。

开发自定义 API 的原因是 JDK 需要一个能够跟上其六个月发布周期的库,并且并不总是落后一个版本。 只有在新的 JDK 版本发布后,ASM 才能适应该版本 - 但新的 ASM 版本只能在下一个 JDK 版本中使用。

由于大多数Java程序员可能永远不会直接接触Class File API,因此我不会在这里详细描述它。

4.JEP 458:启动多文件源代码程序

增强 Java 应用程序启动器,使其能够运行作为多个 Java 源代码文件提供的程序。 这将使从小程序到大程序的过渡更加渐进,使开发人员能够选择是否以及何时配置构建工具。

public class JEP458SayHello {

    public static String sayHello(String name) {
        return "Hello %s!%n".formatted(name);
    }

}
public class JEP458 {

    public static void main(String[] args) {
        System.out.println(JEP458SayHello.sayHello(args[0]));
    }

}
java JEP458.java coding

java JEP458.java coding

4.JEP 459:字符串模板(第二次预览)

使用字符串模板增强 Java 编程语言。 字符串模板通过将文字文本与嵌入式表达式和模板处理器耦合来生成专门的结果,从而补充了 Java 现有的字符串文字和文本块。 这是预览语言功能和 API。

import static java.lang.StringTemplate.STR;

public class JEP459 {

    public static void main(String[] args) {
        int a = 2;
        int b = 4;

        String interpolated = STR."\{a} times \{b} = \{Math.multiplyExact(a, b)}";

        System.out.println("result:"+interpolated);
    }

}
javac --enable-preview --source 22 -Xlint:preview JEP459.java

javac --enable-preview --source 22 -Xlint:preview JEP459.java

java --enable-preview JEP459

java --enable-preview JEP459

4.JEP 460:向量API(第七次孵化)

引入 API 来表达向量计算,在运行时可靠地编译为支持的 CPU 架构上的最佳向量指令,从而实现优于同等标量计算的性能。

import jdk.incubator.vector.IntVector;
import jdk.incubator.vector.VectorSpecies;

public class JEP460 {

    private static final VectorSpecies<Integer> SPECIES = IntVector.SPECIES_PREFERRED;

    public static void vectorAddition(int[] a, int[] b, int[] result) {
        int i = 0;
        int upperBound = SPECIES.loopBound(a.length);
        for (i = 0; i < upperBound; i += SPECIES.length()) {
            // 从数据中加载向量
            IntVector va = IntVector.fromArray(SPECIES, a, i);
            IntVector vb = IntVector.fromArray(SPECIES, b, i);
            // 执行逐元素加法
            IntVector vr = va.add(vb);
            // 将结果存储在结果数组中
            vr.intoArray(result, i);
        }
        // 处理剩余元素
        for (; i < a.length; i++) {
            result[i] = a[i] + b[i];
        }
    }



    public static void main(String[] args) {

        int[] a = {1, 2, 3, 4, 5};
        int[] b = {6, 7, 8, 9, 10};
        int[] result = new int[a.length];

        vectorAddition(a, b, result);

        // 输出结果
        for (int r : result) {
            System.out.println(r);
        }

    }
}
javac --add-modules=jdk.incubator.vector --enable-preview --source 22 -Xlint:preview JEP460.java

javac --add-modules=jdk.incubator.vector --enable-preview --source 22 -Xlint:preview JEP460.java

java --add-modules=jdk.incubator.vector  --enable-preview JEP460

java --add-modules=jdk.incubator.vector  --enable-preview JEP460

4.JEP 461:流收集器(预览版)

增强 Stream API 以支持自定义中间操作。 这将允许流管道以现有内置中间操作不易实现的方式转换数据。 这是一个预览 API。

Java Stream API 中有限的中间流操作数量多年来一直受到批评。 除了现有的操作 filter、map、flatMap、mapMulti、distinct、sorted、peak、limit、skip、takeWhile 和 dropWhile 之外,Java 社区还希望看到 window、fold 等方法。

但 JDK 开发人员没有将所有这些方法集成到 JDK 中,而是决定开发一个 API,允许 JDK 开发人员和 Java 社区编写任何中间流操作。

新的 API 称为“Stream Gatherers”,最初将通过 JDK 增强提案 461 作为 Java 22 中的预览功能发布。

与 API 一起,提供了一系列预定义的收集器,例如请求的窗口和折叠操作。

import java.util.List;
import java.util.stream.Gatherers;

public class JEP461 {

    public static void main(String[] args) {

        List<String> words = List.of("1", "2", "3", "4", "5", "6", "7", "8");

        List<List<String>> fixedWindows = words.stream()
                .gather(Gatherers.windowFixed(3))
                .toList();

        System.out.println(fixedWindows);

        List<Integer> numbers = List.of(1, 2, 3, 4, 5);

        List<List<Integer>> slidingWindows = numbers.stream()
                .gather(Gatherers.windowSliding(3))
                .toList();

        System.out.println(slidingWindows);

    }

}
javac --enable-preview --source 22 -Xlint:preview JEP461.java

javac --enable-preview --source 22 -Xlint:preview JEP461.java

java --enable-preview JEP461

java --enable-preview JEP461

4.JEP 462:结构化并发(第二预览版)

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

JDK新特性之结构化并发及演示代码示例

5.JEP 463:隐式声明的类和实例主要方法(第二预览版)

发展 Java 编程语言,以便学生可以编写他们的第一个程序,而无需了解为大型程序设计的语言功能。 学生无需使用单独的语言方言,而是可以为单类程序编写简化的声明,然后随着技能的增长无缝扩展他们的程序以使用更高级的功能。 这是预览版本功能。

5.JEP 464:作用域值(第二次预览版)

引入作用域值,这使得能够与同一线程中的子帧以及子线程管理不可变数据的共享。 作用域值比线程局部变量更容易推理,并且空间和时间成本更低,特别是与虚拟线程和结构化并发结合使用时。 这是一个预览 API。

  • 30
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值