JDK9-21新特性概览(持续更新)

news2024/11/17 19:52:14

JDK9-21新特性概览

  • 一、JDK9新特性
    • 1.1 JEP 102: Process API Updates
      • 简介
      • 案例
      • 风险
    • 1.2 JEP 193: Variable Handles
      • 简介
      • 案例
      • 风险
    • 1.3 JEP 200: The Modular JDK
      • 简介
      • 案例
      • 风险
    • 1.4 JEP 213: Milling Project Coin
      • 简介
      • 案例
        • 1.1 try-with-resources增强
        • 1.2 接口中私有方法
    • 1.5 JEP 222: jshell: The Java Shell (Read-Eval-Print Loop)
    • 1.6 JEP 254: Compact Strings
    • 1.7 JEP 248: Make G1 the Default Garbage Collector
    • 1.8 JEP 264: Platform Logging API and Service
    • 1.9 JEP 270: Reserved Stack Areas for Critical Sections
      • 简介
      • 案例
    • 2.0 JEP 269: Convenience Factory Methods for Collections
      • 简介
      • 案例
    • 2.1 JEP 271: Unified GC Logging
    • 2.2 JEP 280: Indify String Concatenation
      • 简介
      • 案例
      • 优点
    • 2.3 JEP 285: Spin-Wait Hints
      • 简介
      • 案例
      • 优点
    • 其他
      • InputStream增强
      • Stream API的增强
  • 二、 JDK11 新特性(TODO)
  • 三、JDK13新特性(TODO)
  • 四、JDK15新特性(TODO)

一、JDK9新特性

1.1 JEP 102: Process API Updates

简介

该提议旨在改进 Java 程序对操作系统进程管理的支持,主要通过对 java.lang.Processjava.lang.ProcessHandle 增强,方便更好管控操作系统进程资源。

案例

ProcessHandle currentProcess = ProcessHandle.current();
long currentPid = currentProcess.pid();
ProcessHandle.Info info = currentProcess.info();

System.out.printf("Current Process PID: %d%n", currentPid);
info.command().ifPresent(cmd -> System.out.printf("Command: %s%n", cmd));
info.startInstant().ifPresent(start -> System.out.printf("Start time: %s%n", start));
info.totalCpuDuration().ifPresent(cpu -> System.out.printf("CPU usage: %s%n", cpu));

// 获取并管理当前进程的所有子进程
currentProcess.children().forEach(child -> {
    System.out.printf("Child PID: %d%n", child.pid());
    child.destroy(); // 销毁子进程
    // 监听当前进程的状态变化
    child.onExit().thenRun(() -> System.out.println("Process has exited"));
});

风险

跨平台的时候,需要考虑不同操作系统的差异。

1.2 JEP 193: Variable Handles

简介

变量句柄(Variable Handles)是对Java内存模型进行的一次重要增强。变量句柄是对Java中的变量进行更灵活和高效访问的机制,主要是方便对一个类中的变量进行细粒度的管控,类似于安全的反射,具有更高的性能和类型安全。它们提供了一组方法来读取和写入变量,并且可以原子地操作这些变量。

变量句柄提供了一种统一的方式来访问各种类型的变量,包括字段、数组元素和静态变量。它们在并发编程中尤为有用,因为它们支持高级的同步操作和内存屏障。

由单个抽象类java.lang.invoke.VarHandlejava.lang.invoke.MethodHandles实现,VarHandle中包含了不同的访问模式,是多态的一种体现。

  1. 读访问模式,读最新的变量值
  2. 写访问模式,对变量的更新对其他线程可见
  3. 原子更新访问模式
  4. 数字原子更新访问模式,例如getAndAdd。
  5. 位原子更新访问模式,如getAndbitwise

案例

public class VariableHandleExample {
    // 声明实例字段和静态变量句柄
    private int x;
    private static VarHandle X_HANDLE;

    // 声明数组和数组元素句柄
    private final int[] array = new int[10];
    private static VarHandle ARRAY_HANDLE;

    static {
        try {
            // 初始化实例字段的变量句柄
            X_HANDLE = MethodHandles.lookup ().findVarHandle (VariableHandleExample.class, "x", int.class);
            // 初始化数组元素的变量句柄
            ARRAY_HANDLE = MethodHandles.arrayElementVarHandle(int[].class);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace ();
        }
    }

    // 使用变量句柄获取实例字段x的值
    public int getX() {
        return (int) X_HANDLE.get(this);
    }

    // 使用变量句柄设置实例字段x的值
    public void setX(int value) {
        X_HANDLE.set(this, value);
    }

    // 使用变量句柄进行实例字段x的原子比较并交换操作
    public boolean compareAndSetX(int expected, int newValue) {
        return X_HANDLE.compareAndSet(this, expected, newValue);
    }

    // 使用变量句柄获取数组元素的值
    public int getElement(int index) {
        return (int) ARRAY_HANDLE.get(array, index);
    }

    // 使用变量句柄设置数组元素的值
    public void setElement(int index, int value) {
        ARRAY_HANDLE.set(array, index, value);
    }

    public static void main(String[] args) {
        VariableHandleExample example = new VariableHandleExample();

        // 设置和获取实例字段x的值
        example.setX(42);
        System.out.println("Value of x: " + example.getX()); // 输出:Value of x: 42

        // 原子比较并交换操作
        boolean updated = example.compareAndSetX(42, 100);
        System.out.println("Updated: " + updated); // 输出:Updated: true
        System.out.println("Value of x: " + example.getX()); // 输出:Value of x: 100

        // 设置和获取数组元素的值
        example.setElement(0, 123);
        System.out.println("Value at index 0: " + example.getElement(0)); // 输出:Value at index 0: 123
    }
}

风险

性能还需要更多的验证。

1.3 JEP 200: The Modular JDK

简介

将JDK划分为一组模块,这些模块可以在编译时、构建时和运行时组合成各种配置,更易于提高安全性和可维护性,提高应用程序性能,并为开发人员提供更好的大型编程工具。

整个流程大致分为三步:

  1. 使用moudule-info.java来声明一个模块,一个模块只能有一个文件,且在顶层包同目录下
  2. 使用exports来声明可以被外部引用的包可以有多个exports语句
  3. 使用requires来声明依赖的外部的模块可以有多个requires语句

案例

module 被引用模块 {
	// 导出的子模块
    exports com.nju.jdk9;
}

module 引用模块{
	// 引用的子模块
    requires jdk9;
}

风险

有些用例不能支持,还存在一些缺陷,留待后续迭代的时候进行完善。

1.4 JEP 213: Milling Project Coin

简介

主要是对语言的细微改进来提高Java的可读性和可维护性。

  1. try-with-resources使用的简化
  2. 允许接口中私有方法,只能在该接口内部使用,主要用于重用代码,减少重复。

案例

1.1 try-with-resources增强
import java.io.*;

public class TryWithResourcesExample {
    public static void main(String[] args) throws IOException {
        // 在 try 块外部声明和初始化资源
        Reader reader = new BufferedReader(new FileReader("test.txt"));
        try (reader) {
            // 使用资源
            System.out.println(reader.read());
        }
    }
}

1.2 接口中私有方法
interface MyInterface {
    default void doSomething() {
        sayHello ();
        sayGoodBye();
    }

    void sayGoodBye();

    private void sayHello() {
        System.out.println ("hello");
    }
}

public class PrivateInterfaceImpl implements MyInterface{
    public static void main(String[] args) {
        PrivateInterfaceImpl impl = new PrivateInterfaceImpl ();
        impl.doSomething ();
    }

    @Override
    public void sayGoodBye() {
        System.out.println ("bye");
    }
}

1.5 JEP 222: jshell: The Java Shell (Read-Eval-Print Loop)

新增JShell控制台进行交互编程(就跟python一样,直接控制台编码,输出)

1.6 JEP 254: Compact Strings

之前的JDK版本采用char数组存储字符串,char默认两个字节存储,JDK9采用byte数组更加节约存储空间

1.7 JEP 248: Make G1 the Default Garbage Collector

使用G1作为默认的垃圾收集器,减少GC期间STW(Stop the World)的时间,以提供更好的用户体验。

1.8 JEP 264: Platform Logging API and Service

提供了更轻量级的默认的日志APIjava.util.logging

1.9 JEP 270: Reserved Stack Areas for Critical Sections

简介

给线程栈预留了更多的空间,减少并发情况下StackOverflow风险,避免进一步的并发问题,如死锁。

当一个临界区由几个方法组成时,例如一个方法a调用了一个方法b,可用的堆栈足以让方法a执行。方法a开始修改数据结构,然后调用方法b,但是剩余的堆栈不足以执行b,导致StackOverflowError。因为方法b和方法a的剩余部分没有执行,所以数据结构的一致性可能已经受到损害。

案例

// 无法保证原子操作
final void lock() {
    if (compareAndSetState(0, 1))
        setExclusiveOwnerThread(Thread.currentThread());
    else
        acquire(1);
}

2.0 JEP 269: Convenience Factory Methods for Collections

简介

通过工厂方法,用于创建不可变的集合实例。这些方法通过java.util.List, java.util.Set, 和 java.util.Map接口中的静态方法实现,使得创建集合对象的语法更加简洁、清晰。

案例

public class CollectionsExample {
    public static void main(String[] args) {
        // 使用List.of()创建不可变的列表
        List<String> list = List.of("one", "two", "three");
        System.out.println("List: " + list); // 输出: List: [one, two, three]

        // 尝试修改列表会抛出UnsupportedOperationException
        // list.add("four"); // 这行代码会抛出异常

        // 使用Set.of()创建不可变的集合
        Set<String> set = Set.of("one", "two", "three");
        System.out.println("Set: " + set); // 输出: Set: [one, two, three]

        // 尝试修改集合会抛出UnsupportedOperationException
        // set.add("four"); // 这行代码会抛出异常

        // 使用Map.of()创建不可变的映射
        Map<String, Integer> map = Map.of("one", 1, "two", 2, "three", 3);
        System.out.println("Map: " + map); // 输出: Map: {one=1, two=2, three=3}

        // 使用Map.ofEntries()创建不可变的映射
        Map<String, Integer> mapEntries = Map.ofEntries(
                Map.entry("one", 1),
                Map.entry("two", 2),
                Map.entry("three", 3)
        );
        System.out.println("Map with Entries: " + mapEntries); // 输出: Map with Entries: {one=1, two=2, three=3}

        // 尝试修改映射会抛出UnsupportedOperationException
        // map.put("four", 4); // 这行代码会抛出异常
    }
}

2.1 JEP 271: Unified GC Logging

提供统一的GC日志API。log_info(gc, heap, ergo)("Heap expanded"); 通过GC tag的来控制打印哪些内容。

2.2 JEP 280: Indify String Concatenation

简介

旨在通过使用invokedynamic(java.lang.invoke.StringConcatFactory)指令来优化字符串连接操作。这种方法使用invokedynamic指令,并将连接逻辑推迟到运行时,以便可以更好地利用JVM的优化能力。

在Java 9之前,字符串连接通常是通过StringBuilder的隐式使用来实现的。

案例

String m(String a, int b) {
  return a + "(" + b + ")";
}

其中JDK8编译上述代码后:JDK8编译
JDK9编译上述代码后:
在这里插入图片描述

优点

  • 性能优化:通过将字符串连接推迟到运行时,JVM可以应用更高效的优化策略。
  • 减少内存开销:避免了大量的StringBuilder对象的创建和销毁,降低了GC压力。
  • 灵活性:运行时优化允许JVM根据具体情况选择最佳的连接策略,适应不同的硬件和JVM实现。

2.3 JEP 285: Spin-Wait Hints

简介

引入了“旋转等待提示”(Spin-Wait Hints),即在多线程编程中提供一种机制,通过标准化的方法向底层处理器传达线程处于“自旋等待”(spin-wait)的状态,在 java.lang.Thread.onSpinWait() 中实现自旋等待提示。

案例

public class SpinWaitExample {
    private volatile boolean condition = false;

    public void waitForCondition() {
        while(!condition) {
            Thread.onSpinWait ();
        }
        System.out.println ("Condition change to true");
    }

    public void setCondition() {
        condition = true;
    }

    public static void main(String[] args) throws InterruptedException {
        SpinWaitExample example = new SpinWaitExample ();
        Thread waiter = new Thread (example::waitForCondition);
        waiter.start ();

        Thread.sleep (1000);

        example.setCondition ();
        waiter.join ();
    }
}

优点

  • 提高性能:自旋等待提示允许处理器优化资源利用和功耗管理,在高性能计算场景中特别有用。
  • 降低延迟:适用于需要低延迟同步的场景,例如高频交易系统或实时处理系统。
  • 标准化:提供了一个标准API,避免了使用特定于平台的低级指令,提高了代码的可移植性。

其他

InputStream增强

新增了transferTo方法,可以用来将数据直接传输到 OutputStream

Stream API的增强

public class StreamApiExample {
    public static void main(String[] args) {
        testForTakeWhile();
        testForDropWhile();
        testForOfNullable();
        testForIterate();
    }

    //  takeWhile用于从 Stream 中获取一部分数据,接收一个 Predicate 来选择从开头开始的满足条件的元素。
    public static void testForTakeWhile(){
        List<Integer> list = Arrays.asList(10,20,30,40,30,20,10);
        list.stream().takeWhile(t->t<40).forEach(t -> System.out.print(t + " "));
        System.out.println ();

        List<Integer> list2 = Arrays.asList(1,2,3,4,5,6,7);
        list2.stream().takeWhile(t->t<7).forEach(t -> System.out.print(t + " "));
        System.out.println ();
    }

    // dropWhile 的行为与 takeWhile 相反,返回剩余的元素
    public static void testForDropWhile() {
        List<Integer> list = Arrays.asList(10,20,30,40,30,20,10);
        list.stream().dropWhile(t->t<40).forEach(t-> System.out.print(t + " "));
        System.out.println ();

        List<Integer> list2 = Arrays.asList(1,2,3,4,5,6,7);
        list2.stream().dropWhile(t->t<7).forEach(t -> System.out.print(t + " "));
        System.out.println ();
    }

    // ofNullable 方法允许我们创建一个Stream,可以所有元素均为空。
    public static void testForOfNullable() {
        // JDK8允许通过
        Stream<String> streams = Stream.of("AA","BB",null);
        System.out.println(streams.count());
        // JDK8不允许通过
        /*Stream<Object> stream2 = Stream.of(null);
        System.out.println(stream2.count());*/
        // JDK9允许通过
        Stream<Object> stream2 = Stream.ofNullable(null);
        System.out.println(stream2.count());
    }

    // iterate 可以让你提供一个 Predicate (判断条件)来指定什么时候结束迭代。
    public static void testForIterate() {
        // 原始方式
        Stream.iterate(1,i->i+1).limit(50).forEach(t -> System.out.print(t + " "));
        System.out.println ();

        // 增强方式
        Stream.iterate(1,i->i<60,i->i+1).forEach(t -> System.out.print(t + " "));
    }
}

二、 JDK11 新特性(TODO)

三、JDK13新特性(TODO)

四、JDK15新特性(TODO)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1710882.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Sentinel-2 哨兵二号数据介绍及下载

1 Sentinel-2简介 SENTINEL-2 is a European wide-swath, high-resolution, multi-spectral imaging mission. Sentinel-2 是高分辨率多光谱成像卫星&#xff0c;一颗卫星的重访周期为10天&#xff0c;两颗互补&#xff0c;重访周期为5天。分为2A和2B两颗卫星。2A于2015年6月…

【Mybatis】映射文件中获取参数的类型是集合或数组处理

基本数据类型的参数或者对象作为参数的情况&#xff0c;在Mybatis还有一些特殊处理的参数类型要特别注意&#xff1a;如果参数类型是集合Collection&#xff08;List&#xff0c;Set&#xff09;或者是数组&#xff0c;Mybatis也会把这些类型的参数封装在一个Map对象中传递到xm…

电脑记事软件哪款安全?好用且安全的桌面记事工具

在快节奏的现代生活中&#xff0c;我们每天都要用电脑处理大量的工作。电脑不仅提升了工作效率&#xff0c;还成为了我们记录重要事项和灵感的得力助手。比如&#xff0c;在策划项目时&#xff0c;我会直接在电脑上列出要点和步骤&#xff1b;在开会时&#xff0c;我也会用电脑…

Python | Leetcode Python题解之第117题填充每个节点的下一个右侧节点指针II

题目&#xff1a; 题解&#xff1a; class Solution:def connect(self, root: Node) -> Node:if not root:return Nonestart rootwhile start:self.last Noneself.nextStart Nonep startwhile p:if p.left:self.handle(p.left)if p.right:self.handle(p.right)p p.nex…

【Mybatis】映射文件中获取单个参数和多个参数的写法

xml的映射文件中获取接口方法中传来的参数是直接用#{}的方式来获取的 那么接下来&#xff0c;我们就具体来说一下获取参数里边的各种规则和用法 1.单个参数&#xff0c;比如上面的getOneUser&#xff0c;只有一个id值作为参数 Mybatis对于只有一个参数的情况下&#xff0c;不…

【深度学习】Transformer梳理

零、前言 对于transformer&#xff0c;网上的教程使用记号、术语不一 。 最关键的一点&#xff0c;网上各种图的简化程度不一 &#xff08;画个图怎么能这么偷懒&#xff09; &#xff0c;所以我打算自己手画一次图。 看到的最和善&#xff08;但是不是那么靠谱&#xff0c;我…

Qt 项目(CMake)支持多国语言(2024/05)

目录 1.在工程手动创建languages文件夹2.修改CMakeLists.txt3.在qml上随便添加一下文字内容4.执行CMake5.把.ts和.qm添加到项目中6.翻译成英文的示例7.在main里面加载语言文件8.启动软件自动获取电脑的语言遗留问题 参考:Qt 项目(CMake)设置国际化支持 1.在工程手动创建langua…

AIGC中国开发者大会:AI Agent中国落地发展现状及多模态结合具身智能的发展展望

引言 2024年5月25日&#xff0c;第三届AIGC中国开发者大会在昆仑巢成功举办。本次大会围绕“AI Agent的国内应用现状及多模态结合具身智能的发展展望”这一主题&#xff0c;邀请了多位知名企业家、投资人以及技术专家&#xff0c;共同探讨大模型在中国各行各业的应用现状及未来…

基于粒子群算法的网络最优节点部署优化matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于粒子群算法的网络最优节点部署优化,实现WSN网络的节点覆盖最大化。 2.测试软件版本以及运行结果展示 MATLAB2022A版本运行 3.核心程序 .................…

Paddle Inplace 使用指南

Paddle Inplace 使用指南 1. 引言 在深度学习领域&#xff0c;框架的选择对模型的训练效率和资源消耗有着直接的影响。PaddlePaddle&#xff08;飞桨&#xff09;是一个由百度开发的全面、灵活和高效的深度学习平台。本文旨在介绍和分享 Paddle Inplace 机制的使用指南&#…

Java | Leetcode Java题解之第117题填充每个节点的下一个右侧节点指针II

题目&#xff1a; 题解&#xff1a; class Solution {Node last null, nextStart null;public Node connect(Node root) {if (root null) {return null;}Node start root;while (start ! null) {last null;nextStart null;for (Node p start; p ! null; p p.next) {if…

树莓派指令

1.常用指令 2.在终端窗口编辑文本文件 2.1nano编辑器 在文本里ctrlG就可以查看更多的快捷按键 2.2vi编辑器 进入默认为命令模式

【机器学习】MS_MARCO_Web_Search解析说明

MS MARCO Web Search&#xff1a;引领大型模型与信息检索的新纪元 一、引言&#xff1a;大型模型与信息检索的挑战二、MS MARCO Web Search数据集的特点三、MS MARCO Web Search数据集的应用五、结语 在信息爆炸的时代&#xff0c;如何高效、准确地从海量数据中检索出有价值的信…

opencascade V3d_PositionLight V3d_SpotLight 源码学习 (位置性)光源

Positional、Spot 和 Directional Light 类的基类。 类V3d_SpotLight 创造和修改光源的衰减因子 F 决定了表面的照明&#xff1a; F 1 / (ConstAttenuation() LinearAttenuation() * Distance) 其中 Distance 是从光源到表面的距离。默认值 (1.0, 0.0) 对应最小的衰减。浓…

数组长度属性的安排与深度学习中的数据类型探索

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、数组长度属性的理解与应用 1. 数组形状信息的获取 2. 数组形状的变换 3. 数组类型的指…

串口触摸屏键盘工作机理

一&#xff1a;键盘的实现原理 PW 是否显示为密码(内容仍为实际内容,仅仅显示出来为*):0-否;1-是。 可读&#xff0c;可通过上位机修改&#xff0c;可通过指令修改。 covx-变量类型转换? 串口屏上仅有两种数据类型&#xff0c;即数值和字符串类型&#xff0c;当需要将字符串…

UE5 UE4 快速定位节点位置

在材质面板中&#xff0c;找到之前写的一个节点&#xff0c;想要修改&#xff0c;但是当时写的比较多&#xff0c;想要快速定位到节点位置. 在面板下方的 Find Results面板中&#xff0c;输入所需节点&#xff0c;找结果后双击&#xff0c;就定位到该节点处。 同理&#xff0c;…

APM2.8如何做加速度校准

加速度的校准建议准备一个六面平整&#xff0c;边角整齐的方形硬纸盒或者塑料盒&#xff0c;如下图所示&#xff0c;我们将以它作为APM校准时的水平垂直姿态参考&#xff0c;另外当然还需要一块水平的桌面或者地面 首先用双面泡沫胶或者螺丝将APM主板正面向上固定于方形盒子上&…

每天五分钟深度学习:如何使用计算图来反向计算参数的导数?

本文重点 在上一个课程中&#xff0c;我们使用一个例子来计算函数J&#xff0c;也就相当于前向传播的过程&#xff0c;本节课程我们将学习如何使用计算图计算函数J的导数。相当于反向传播的过程。 计算J对v的导数&#xff0c;dJ/dv3 计算J对a的导数&#xff0c;dJ/da&#xf…

计算机组成原理----移码

在网上搜索移码是什么,大概率会搜到一个结论:移码是补码符号位取反,可是真的是这样吗? 传统的有符号整数是将二进制数的首位作为符号位,0表示正数,1表示负数。 但在移码中,我们不再使用单独的符号位来表示正负。而是通过一个固定的偏置量来将所有可能的指数值映射到一个无符…