Java 20 新功能介绍

这篇具有很好参考价值的文章主要介绍了Java 20 新功能介绍。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

➜  bin pwd
/Users/darcy/develop/jdk-20.0.1.jdk/Contents/Home/bin
➜  bin ./java -version
openjdk version "20.0.1" 2023-04-18
OpenJDK Runtime Environment (build 20.0.1+9-29)
OpenJDK 64-Bit Server VM (build 20.0.1+9-29, mixed mode, sharing)

Java 20 共带来 7 个新特性功能,其中三个是孵化提案,孵化也就是说尚在征求意见阶段,未来可能会删除此功能。

JEP 描述 分类
429 作用域值(孵化器) Project Loom,Java 开发相关
432 Record 模式匹配(第二次预览) Project Amber,新的语言特性
433 switch 的模式匹配(第四次预览) Project Amber,新的语言特性
434 外部函数和内存 API(第二个预览版) Project Panama,非 Java 库
436 虚拟线程(第二个预览版) Project Loom,Java 开发相关
437 结构化并发(第二孵化器) Project Loom,Java 开发相关
438 Vector API(第五孵化器) Project Panama,非 Java 库

JEP:JDK Enhancement Proposal,JDK 增强建议,或者叫 Java 未来发展建议。

JDK 20 不是长期支持 (LTS) 版本,因此它只会在六个月后被 JDK 21 取代之前收到更新。JDK 17( 2021 年 9 月 14 日发布)是 Java 的最新 LTS 版本。Oracle 宣布计划将 LTS 版本之间的时间从三年缩短到两年,因此 JDK 21(2023 年 9 月)计划成为下一个LTS。

Java 20 安装

Java 20 OpenJDK 下载:https://jdk.java.net/19/

Java 20 OpenJDK 文档:https://openjdk.java.net/projects/jdk/20/

Java 20 OracleJDK 下载:Oracle JDK 20 Archive Downloads

# 此文中示例代码运行都在 Java 20 环境下使用命令
➜  src $ /jdk-20.0.1.jdk/Contents/Home/bin/java --version                                                         
openjdk 20.0.1 2023-04-18
OpenJDK Runtime Environment (build 20.0.1+9-29)
OpenJDK 64-Bit Server VM (build 20.0.1+9-29, mixed mode, sharing)
➜  src $ /jdk-20.0.1.jdk/Contents/Home/bin/java  --add-modules jdk.incubator.concurrent Xxx.java
WARNING: Using incubator modules: jdk.incubator.concurrent
hello wdbyte
没有信息

JEP 429: Scoped Value

在线程之间共享变量不是一件简单的事,可以使用 ThreadLocal 来保存当前线程变量,但是需要手动清理,开发者常常忘记,且变量不能被子线程继承;而使用 InheritableThreadLocal 共享信息可以被子线程继承,但是数据会拷贝多份,占用更多内存。

引入Scoped values允许在线程内和线程间共享不可变数据,这比线程局部变量更加方便,尤其是在使用大量虚拟线程时。这提高了易用性、可理解性、健壮性以及性能。不过这是一个正在孵化的 API,未来可能会被删除。

scoped values 有下面几个目标:

  • 易用性——提供一个编程模型来在线程内和子线程之间共享数据,从而简化数据流的推理。
  • 可理解性——使共享数据的生命周期从代码的句法结构中可见。
  • 稳健性——确保调用者共享的数据只能由合法的被调用者检索。
  • 性能——将共享数据视为不可变的,以便允许大量线程共享,并启用运行时优化。

例子

如果每个请求都是用一个单独的线程来处理,现在需要接受一个请求,然后根据不同身份访问数据库,那么我们可以用传递参数的方式,直接把身份信息在调用访问数据库方法时传递过去。如果不这么做,那么就要使用 ThreadLocal 来共享变量了。

Thread 1                             Thread 2
--------                             --------
8. 数据库 - 开始查询 ()                8. throw new InvalidPrincipalException()
7. 数据库 - 开始访问 () <---+          7. 数据库 - 开始访问 () <---+ 
   ...                    |             ...                   |
   ...                身份(管理员)        ...                  身份(访客)
2. 开始处理(..)            |          2. 开始处理(..)            |
1. 收到请求(..) -----------+          1. 收到请求(..) -----------+   

示意代码:

class Server {
    final static ThreadLocal<Principal> PRINCIPAL = new ThreadLocal<>();  

    void serve(Request request, Response response) {
        var level     = (request.isAuthorized() ? ADMIN : GUEST);
        var principal = new Principal(level);
        PRINCIPAL.set(principal);                                         
        Application.handle(request, response);
    }
}

class DBAccess {
    DBConnection open() {
        var principal = Server.PRINCIPAL.get();                           
        if (!principal.canOpen()) throw new InvalidPrincipalException();
        return newConnection(...);                                        
    }
}

这是我们常见的写法,但是使用 ThreadLocal 的问题是:

  • PRINCIPAL.set(principal) 可以被任意设置修改。
  • 使用 ThreadLocal 可能会忘记 remove
  • 如果想要子线程继承共享的变量,需要占用新的内存空间
  • 在虚拟线程场景下,可能会有几十万线程,使用 ThreadLocal 过于复杂,且有安全性能隐患。

虚拟线程自 Java 19 引入:JEP 425: 虚拟线程 (预览)

使用 ScopedValue

import jdk.incubator.concurrent.ScopedValue;

/**
 * 启动命令加上 --add-modules jdk.incubator.concurrent
 *
 * @author https://www.wdbyte.com
 */
public class Jep429ScopedValueTest {
    final static ScopedValue<String> SCOPED_VALUE = ScopedValue.newInstance();

    public static void main(String[] args) {
        // 创建线程
        Thread thread1 = new Thread(Jep429ScopedValueTest::handle);
        Thread thread2 = new Thread(Jep429ScopedValueTest::handle);
        String str = "hello wdbyte";
        // 传入线程里使用的字符串信息
        ScopedValue.where(SCOPED_VALUE, str).run(thread1);
        ScopedValue.where(SCOPED_VALUE, str).run(thread2);
        // 执行完毕自动清空,这里获取不到了。
        System.out.println(SCOPED_VALUE.orElse("没有信息"));
    }
    public static void handle() {
        String result = SCOPED_VALUE.get();
        System.out.println(result);
    }
}

运行:

➜  src $ /jdk-20.0.1.jdk/Contents/Home/bin/java --version                                                         
openjdk 20.0.1 2023-04-18
OpenJDK Runtime Environment (build 20.0.1+9-29)
OpenJDK 64-Bit Server VM (build 20.0.1+9-29, mixed mode, sharing)
  
➜  src $ /jdk-20.0.1.jdk/Contents/Home/bin/java  --add-modules jdk.incubator.concurrent Jep429ScopedValueTest.java
WARNING: Using incubator modules: jdk.incubator.concurrent
hello wdbyte.com
hello wdbyte.com  
没有信息

可见使用 ScopedValue 有几个显而易见的好处。

  • 代码方便,容易理解。符合编程逻辑。
  • 不允许修改值,安全性高。(没有 set 方法)
  • 生命周期明确。只传递到 run() 方法体中。
  • 不需要清理,自动释放。
  • 从实现来讲,也是一种轻量级实现。

JEP 432: Record 模式匹配(二次预览)

在 Java 14 的 JEP 359 中增加了 Record 类,在 Java 16 的 JEP 394中,新增了 instanceof 模式匹配。

这两项都简化了 Java 开发的代码编写。在 Java 19 的 JEP 405 中,增又加了 Record 模式匹配功能的第一次预览,这把 JEP 359 和 JEP 394 的功能进行了结合,但是还不够强大,现在 JEP 432 又对其进行了增强。

JEP 359 功能回顾:

/**
 * @author https://www.wdbyte.com
 */
public class RecordTest {
    public static void main(String[] args) {
        Dog dog = new Dog("name", 1);
        System.out.println(dog.name()); // name
        System.out.println(dog.age());  // 1
    }
}

record Dog(String name, Integer age) {
}

JEP 394 功能回顾:

// Old code
if (obj instanceof String) {
    String s = (String)obj;
    ... use s ...
}

// New code
if (obj instanceof String s) {
    ... use s ...
}

JEP 432 例子

而现在,可以进行更加复杂的组合嵌套,依旧可以准确识别类型。

/**
 * @author https://www.wdbyte.com
 */
public class Jep432RecordAndInstance {
    public static void main(String[] args) {
        ColoredPoint coloredPoint1 = new ColoredPoint(new Point(0, 0), Color.RED);
        ColoredPoint coloredPoint2 = new ColoredPoint(new Point(1, 1), Color.GREEN);
        Rectangle rectangle = new Rectangle(coloredPoint1, coloredPoint2);
        printUpperLeftColoredPoint(rectangle);
    }

    static void printUpperLeftColoredPoint(Rectangle r) {
        if (r instanceof Rectangle(ColoredPoint ul, ColoredPoint lr)) {
            System.out.println(ul.c());
        }
    }
}

record Point(int x, int y) {}
enum Color { RED, GREEN, BLUE }
record ColoredPoint(Point p, Color c) {}
record Rectangle(ColoredPoint upperLeft, ColoredPoint lowerRight) {}

输出:RED

JEP 433: switch 模式匹配(四次预览)

Switch 的使用体验改造早在 Java 17 就已经开始了,下面是之前文章的一些介绍。

  • JEP 406:switch 的类型匹配(预览)
  • JEP 420:switch 表达式(二次预览)
  • JEP 427: switch 模式匹配 (三次预览)

现在 JEP 433 进行第四次预览,对其功能进行了增强,直接从下面的新老代码看其变化。

/**
 * @author https://www.wdbyte.com
 */
public class JEP433SwitchTest {
    public static void main(String[] args) {
        Object obj = 123;
        System.out.println(matchOld(obj)); // 是个数字
        System.out.println(matchNew(obj)); // 是个数字
        obj = "wdbyte.com";
        System.out.println(matchOld(obj)); // 是个字符串,长度大于2
        System.out.println(matchNew(obj)); // 是个字符串,长度大于2
    }

    /**
     * 老代码
     *
     * @param obj
     * @return
     */
    public static String matchOld(Object obj) {
        if (obj == null) {
            return "数据为空";
        }
        if (obj instanceof String) {
            String s = obj.toString();
            if (s.length() > 2) {
                return "是个字符串,长度大于2";
            }
            if (s.length() <= 2) {
                return "是个字符串,长度小于等于2";
            }
        }
        if (obj instanceof Integer) {
            return "是个数字";
        }
        throw new IllegalStateException("未知数据:" + obj);
    }

    /**
     * 新代码
     *
     * @param obj
     * @return
     */
    public static String matchNew(Object obj) {
        String res = switch (obj) {
            case null -> "数据为空";
            case String s when s.length() > 2 -> "是个字符串,长度大于2";
            case String s when s.length() <= 2 -> "是个字符串,长度小于等于于2";
            case Integer i -> "是个数字";
            default -> throw new IllegalStateException("未知数据:" + obj);
        };
        return res;
    }

}

JEP 434: 外部函数和内存 API(二次预览)

此功能引入的 API 允许 Java 开发者与 JVM 之外的代码和数据进行交互,通过调用外部函数(JVM 之外)和安全的访问外部内存(非 JVM 管理),让 Java 程序可以调用本机库并处理本机数据,而不会像 JNI 一样存在很多安全风险。

这不是一个新功能,自 Java 14 就已经引入,此次对其进行了性能、通用性、安全性、易用性上的优化。

历史

  • Java 14 JEP 370 引入了外部内存访问 API(孵化器)。
  • Java 15 JEP 383 引入了外部内存访问 API(第二孵化器)。
  • Java 16 JEP 389 引入了外部链接器 API(孵化器)。
  • Java 16 JEP 393 引入了外部内存访问 API(第三孵化器)。
  • Java 17 JEP 412 引入了外部函数和内存 API(孵化器)。
  • Java 18 JEP 419 引入了外部函数和内存 API(二次孵化器)。
  • Java 19 JEP 424 引入了外部函数和内存 API(孵化器)。

JEP 436: 虚拟线程(二次预览)

通过将轻量级虚拟线程引入 Java 平台,简化了编写、维护和观察高吞吐量、并发应用程序的过程。使开发人员能够使用现有的 JDK 工具和技术轻松地排除故障、调试和分析并发应用程序,虚拟线程有助于加速应用程序开发。

这个特性自 Java 19 的 JEP 425: 虚拟线程 (预览)引入,在 Java 19 已经进行了详细介绍。

JEP 425: 虚拟线程 (预览)

JEP 437: Structured Concurrency(二次孵化)

通过引入用于结构化并发 API 来简化多线程编程。结构化并发将在不同线程中运行的多个任务视为单个工作单元,从而简化错误处理,提高可靠性,增强可观察性。因为是个孵化状态提案,这里不做过多研究。

  • 相关 Java 19,JEP 428:结构化并发(孵化)

JEP 438: Vector API(五次孵化)

再次提高性能,实现优于等效标量计算的性能。这是通过引入一个 API 来表达矢量计算,该 API 在运行时可靠地编译为支持的 CPU 架构上的最佳矢量指令,从而实现优于等效标量计算的性能。Vector API 在 JDK 16 到 19 中孵化。JDK 20 整合了这些版本用户的反馈以及性能改进和实现增强。

一如既往,文章中代码存放在 Github.com/niumoo/javaNotes.

文章持续更新,可以微信搜一搜「 程序猿阿朗 」或访问「程序猿阿朗博客 」第一时间阅读。本文 Github.com/niumoo/JavaNotes 已经收录,有很多系列文章,欢迎Star。文章来源地址https://www.toymoban.com/news/detail-434794.html

到了这里,关于Java 20 新功能介绍的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++11 新功能

    在2003年C++标准委员会曾经提交了一份技术勘误表(简称TC1),使得C++03这个名字已经取代了C++98称为 C++11之前的最新C++标准名称。不过由于TC1主要是对C++98标准中的漏洞进行修复,语言的核心部分则没 有改动,因此人们习惯性的把两个标准合并称为C++98/03标准。从C++0x到C++11,C+

    2023年04月12日
    浏览(58)
  • Midjourney新功能:角色参照指南

    基本概念 角色参照(Character Reference) :这个功能允许用户在不同的图像生成中保持给定参照角色的一致性。 适用模型 :适用于Midjourney V6和Niji6型号。 功能亮点 跨风格一致性 :可以在不同风格(如动漫风、写实风)中保持角色特征一致。 面部、着装、发型调控 :用户可以

    2024年04月10日
    浏览(60)
  • 【C++】C++11 -- 新功能

    在C++11之前一个类有6个默认成员函数,在C++11标准中又新增了两个默认成员函数,分别是移动构造函数和移动赋值函数 默认移动构造和移动赋值生成的条件 移动构造函数的生成条件:没有自己实现移动构造函数,并且没有自己实现析构函数,拷贝构造函数和拷贝赋值函数 移

    2024年02月17日
    浏览(50)
  • TypeScript 5.1发布,新功能更新

    1:返回类型增加undefined 这里设置了一个别名 fun,当时使用它的时候,我们必须显示返回一个 undefined 。 现在你可以直接设置返回类型: 而不仅限于 void any 。 4.3版本 :❌ 5.1版本 :✅ 2:getter可以设置和 setter 的不相关类型 在之前版本 ,get 返回类型应该为 set 的子类型,如

    2024年02月09日
    浏览(50)
  • SOLIDWORKS 2023新功能揭秘(一):3D CAD功能的十大更新

    SolidWorks 3D CAD  软件拥有设计、模拟、成本估算、可制造性检查、CAM、可持续设计和数据管理等功能,同时还包含适用于钣金,焊件,曲面,模具,产品配置,DFM和CAM的专业工具,支持ECAD/MCAD协作,复杂的零部件库以及高级真实感渲染。更重要的是具有结构和运动分析功能,

    2024年02月05日
    浏览(48)
  • 三星泄露微软 Copilot 新功能:用自然语言操控各种功能

    3 月 11 日消息,微软计划本月晚些时候发布新款 Surface 电脑和适用于 Windows 11 的 Copilot 新功能,但三星似乎等不及了,在其即将推出的 Galaxy Book4 系列产品宣传材料中泄露了一些即将到来的 Copilot 功能。 三星官网上发布的图片证实了此前关于微软正为其人工智能助手 Copilo

    2024年04月09日
    浏览(87)
  • C# 12 预览版的新功能

    作者:Kathleen Dollard 排版:Alan Wang Visual Studio 17.7 Preview 3 和 .NET 8 Preview 6 的发布推进了 C# 12的发展。此预览版包含的功能为将来的性能增强奠定了基础。现在,您能够在库中更方便的使用内联函数。此预览版首次推出了一项实验性功能:拦截器。该功能允许生成器重新路由代

    2024年02月14日
    浏览(44)
  • 揭密.NET 8到底有什么新功能

    .NET 8 是微软于2021年8月24日宣布的下一代编程语言和框架,它是 .NET 宇宙的一部分,与 C# (Common Language Infrastructure) 紧密集成。.NET 8 引入了许多新功能,如原生编译、值类型 (Value Types)、结构化并发 (structured concurrency) 和快速数组 (RapidArray)。.NET 8 还支持本机 (native) AOT (Ahead-Of

    2024年02月03日
    浏览(45)
  • Microsoft Releases .NET 7新功能

    Microsoft Visual Studio是一种统一的开发体验,使开发人员能够跨web、云和设备创建多层应用程序。11月8日,微软发布了该强大开发环境的下一版本:Visual Studio 2022 17.4版。 除了修复许多顶级报告的bug之外,17.4版还包括了许多基于开发者社区建议的新功能,包括: Visual Studio的本

    2024年02月06日
    浏览(47)
  • 【C++】C++11类的新功能

    👀 樊梓慕: 个人主页  🎥 个人专栏: 《C语言》 《数据结构》 《蓝桥杯试题》 《LeetCode刷题笔记》 《实训项目》 《C++》 《Linux》 《算法》 🌝 每一个不曾起舞的日子,都是对生命的辜负 目录 前言 默认成员函数 类成员变量初始化 强制生成默认函数的default 禁止生

    2024年04月17日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包