【Java】Java 17 新特性概览

news2024/11/27 2:34:23

Java 17 新特性概览

  • 1. Java 17 简介
  • 2. Java 17 新特性
    • 类型推断 - 新的 var 关键字
    • 垃圾回收器改进
    • JEP 356 增强的伪随机数生成器
      • (1)提供了一个新接口 RandomGenerator
      • (2)提供了一个新类 RandomGeneratorFactory
      • (3)提供了四个新的专用 RandomGenerator 接口
    • JEP 398 删除弃用的 Applet API
    • JEP 406 - switch 表达式增强
    • JEP 407 - 删除远程方法调用激活机制
    • JEP 409 - 密封类(Sealed Classes)
    • JEP 410 - 删除实验性的 AOT 和 JIT 编译器
    • JEP 411 - 删除弃用的安全管理器
    • JEP 412 - 外部函数和内存 API(孵化)
    • JEP 414 - 向量(Vector) API(第二次孵化)
  • 3. Java 17 升级实战

1. Java 17 简介

Java 11 于 2021年09月14日 正式发布,且为长期支持版本(Long-Term-Support - LTS)。

Spring 6.x 和 Spring Boot 3.x 最低支持的 Java 17,这里敲黑板:Java 17 将是继 Java 8 以来最重要的长期支持版本

下面为 Oracle Java SE 产品的一些关键产品日期示例(Oracle Java SE Product Releases):

在这里插入图片描述

2. Java 17 新特性

类型推断 - 新的 var 关键字

从 Java 10 开始,引入了局部变量类型推断(Local Variable Type Inference)功能,它可以让我们使用关键字 var 声明局部变量(而不是实际类型),而由编译器根据变量初始化的值自动推断出类型。

// Java 8 传统变量声明方法
String str = "pointer";

// Java 10 使用类型推断的变量声明方法
var str = "pointer";

Java 11 允许在 lambda 表达式中使用 var 进行参数声明:

public class VarInLambdaExample {
    public static void main(String[] args) {
        IntStream.of(1, 2, 3, 5, 6, 7)
            .filter((var i) -> i % 2 == 0)
            .forEach(System.out::println);
    }
}

垃圾回收器改进

从 Java 9 开始,G1默认的垃圾收集器。与 Parallel GC 相比,它减少了暂停时间,尽管它的总体吞吐量可能较低。G1 的更新包括将未使用的已提交内存返回给操作系统的能力(JEP 346)。

ZGC 垃圾收集器已在 Java 11 中引入,并已在 Java 15 (JEP 377) 中达到产品状态。它旨在进一步减少停顿。从 Java 13 开始,它也可以将未使用的已提交内存返回给操作系统 (JEP 351)。

JDK 14 中引入了 Shenandoah GC,并在 Java 15 ( JEP 379) 中达到了产品状态。它旨在保持低暂停时间并独立于堆大小。

在 Java 8 中如果您没有手动更改 GC,您仍然使用 Parallel GC。简单地切换到 Java 17 可能会使您的应用程序运行得更快,并具有更一致的方法运行时间。切换到 ZGC 或 Shenandoah 可能会得到更好的结果。

最后,No-Op Garbage Collector(JEP 318),尽管它是一个实验性功能。这个垃圾收集器实际上不做任何工作,因此允许您精确测量应用程序的内存使用情况。如果您想保持尽可能低的内存操作吞吐量,则很有用。

JEP 356 增强的伪随机数生成器

JDK 17 之前,我们可以借助 Random、ThreadLocalRandom 和SplittableRandom 来生成随机数。不过,这 3 个类都各有缺陷,且缺少常见的伪随机算法支持。

Java 17 为伪随机数生成器 (PRNG) 提供新的接口类型和实现,包括可跳转的 PRNG 和另一类可拆分的 PRNG 算法 (LXM)。

PRNGopen in new window 用来生成接近于绝对随机数序列的数字序列。一般来说,PRNG 会依赖于一个初始值,也称为种子,来生成对应的伪随机数序列。只要种子确定了,PRNG 所生成的随机数就是完全确定的,因此其生成的随机数序列并不是真正随机的。

(1)提供了一个新接口 RandomGenerator

它为所有现有的和新的 PRNG 提供了一个统一的 API。 RandomGenerators 提供名为 ints、longs、doubles、nextBoolean、nextInt、nextLong、nextDouble 和 nextFloat 的方法,以及它们当前的所有参数的变化。从而更容易在应用程序中互换使用各种 PRNG 算法。例如:

public class RandomTest {

    public static void main(String[] args) {
        testRandomGenerator(new Random());
        testRandomGenerator(new SplittableRandom());
        testRandomGenerator(ThreadLocalRandom.current());
    }

    static void testRandomGenerator(RandomGenerator randomGenerator) {
        IntStream ints = randomGenerator.ints(50, 0, 10);
        int[] randoms = ints.toArray();
        for (int i : randoms) {
            System.out.println(i);
        }
        System.out.println("random count = " + randoms.length);
    }
}

(2)提供了一个新类 RandomGeneratorFactory

它用于定位和构造 RandomGenerator 实现的实例:

public class RandomTest {

    public static void main(String[] args) {
        testRandomGeneratorFactory("Random");
        testRandomGeneratorFactory("L128X128MixRandom");
        testRandomGeneratorFactory("Xoshiro256PlusPlus");
    }

    static void testRandomGeneratorFactory(String randomGeneratorName) {
        RandomGeneratorFactory<RandomGenerator> factory = RandomGeneratorFactory.of(randomGeneratorName);
        // 使用时间戳作为随机数种子
        RandomGenerator randomGenerator = factory.create(System.currentTimeMillis());

        // 生成随机数
        val nextInt = randomGenerator.nextInt(10);
        System.out.println(nextInt);
    }
}

上述方法还支持如下LXM 系列 PRNG 算法:

  • L32X64MixRandom
  • L32X64StarStarRandom
  • L64X128MixRandom
  • L64X128StarStarRandom
  • L64X256MixRandom
  • L64X1024MixRandom
  • L128X128MixRandom
  • L128X256MixRandom
  • L128X1024MixRandom

以及广泛使用的 PRNG 算法:

  • Xoshiro256PlusPlus

  • Xoroshiro128PlusPlus

(3)提供了四个新的专用 RandomGenerator 接口

  • SplittableRandomGenerator 扩展了 RandomGenerator 并且还提供名为 split 和 splits 的方法。 可拆分性允许用户从现有的 RandomGenerator 生成一个新的 RandomGenerator,这通常会产生统计上独立的结果。

  • JumpableRandomGenerator 扩展了RandomGenerator 并且还提供名为 jump 和 jumps 的方法。 可跳跃性允许用户跳到中等数量的抽签。

  • LeapableRandomGenerator 扩展了 RandomGenerator 并且还提供方法名为leap和leaps的方法。 可跳跃性允许用户跳过大量的抽签。

  • ArbitrarilyJumpableRandomGenerator 扩展了 LeapableRandomGenerator 并且还提供了jump 和 jumps 的方法额外的变体,允许指定任意跳跃距离。

JEP 356: Enhanced Pseudo-Random Number Generators

JEP 398 删除弃用的 Applet API

Applet API 在 Java 17 进行删除。

Applet API 用于编写在 Web 浏览器端运行的 Java 小程序, 在 Java 9 时被标记弃用,但没有删除。

JEP 398: Deprecate the Applet API for Removal

JEP 406 - switch 表达式增强

Java 16 中,JEP 394 扩展了 instanceof 操作符以获取类型模式并执行类型匹配。这种适度的扩展可以简化熟悉的 instanceof-and-cast 习惯用法:

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

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

Java 17 中对 switch 表达式进行了增强,其中包括对 switch 表达式的模式匹配进行了优化。这些改进可以让开发人员更方便地使用 switch 表达式来进行条件判断和分支控制。

// Old code
static String formatter(Object o) {
    String formatted = "unknown";
    if (o instanceof Integer i) {
        formatted = String.format("int %d", i);
    } else if (o instanceof Long l) {
        formatted = String.format("long %d", l);
    } else if (o instanceof Double d) {
        formatted = String.format("double %f", d);
    } else if (o instanceof String s) {
        formatted = String.format("String %s", s);
    }
    return formatted;
}

// New code
static String formatterPatternSwitch(Object o) {
    return switch (o) {
        case Integer i -> String.format("int %d", i);
        case Long l    -> String.format("long %d", l);
        case Double d  -> String.format("double %f", d);
        case String s  -> String.format("String %s", s);
        default        -> o.toString();
    };
}

对于 null 值的判断也进行了优化:

// Old code
static void testFooBar(String s) {
    if (s == null) {
        System.out.println("oops!");
        return;
    }
    switch (s) {
        case "Foo", "Bar" -> System.out.println("Great");
        default           -> System.out.println("Ok");
    }
}

// New code
static void testFooBar(String s) {
    switch (s) {
        case null         -> System.out.println("Oops");
        case "Foo", "Bar" -> System.out.println("Great");
        default           -> System.out.println("Ok");
    }
}

JEP 406: Pattern Matching for switch (Preview)

JEP 407 - 删除远程方法调用激活机制

删除远程方法调用 (RMI) 激活机制,同时保留 RMI 的其余部分。RMI 激活机制已过时且不再使用。

JEP 407: Remove RMI Activation

JEP 409 - 密封类(Sealed Classes)

密封类(Sealed Classes)由 JEP 360 提出,并作为预览功能在 JDK 15 中提供。它们由 JEP 397 再次提出并进行了改进,并作为预览功能在 JDK 16 中提供 。此 JEP 建议在 JDK 17 中最终确定密封类,与 JDK 16 相比没有任何更改。

没有密封类之前,在 Java 中如果想让一个类不能被继承和修改,我们可以使用 final 关键字对类进行修饰。不过,这种方式不太灵活,直接把一个类的继承和修改渠道给堵死了。

密封类可以对继承或者实现它们的类进行限制,这样这个类就只能被指定的类继承

// 抽象类 Shape 只允许 Circle 和 Circle 继承。
public sealed class Shape permits Circle, Circle {
    // Shape 类的定义
}

public final class Circle extends Shape {
    // Circle 类的定义
}

public final class Rectangle extends Shape {
    // Rectangle 类的定义
}

另外,任何扩展密封类的类本身都必须声明为 sealednon-sealedfinal

public final class Circle extends Shape {
}

public non-sealed class Rectangle extends Shape {
}

JEP 409: Sealed Classes

JEP 410 - 删除实验性的 AOT 和 JIT 编译器

在 Java 9 的 JEP 295 引入了实验性的提前 (AOT) 编译器,在启动虚拟机之前将 Java 类编译为本机代码。

在 Java 17,删除实验性的提前 (AOT) 和即时 (JIT) 编译器,因为该编译器自推出以来很少使用,维护它所需的工作量很大。保留实验性的 Java 级 JVM 编译器接口 (JVMCI),以便开发人员可以继续使用外部构建的编译器版本进行 JIT 编译。

JEP 410: Remove the Experimental AOT and JIT Compiler

JEP 411 - 删除弃用的安全管理器

安全管理器可追溯到 Java 1.0,多年来,它一直不是保护客户端 Java 代码的主要方法,也很少用于保护服务器端代码。为了推动 Java 向前发展,Java 17 删除了弃用的安全管理器。

JEP 411: Deprecate the Security Manager for Removal

JEP 412 - 外部函数和内存 API(孵化)

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

下面是 FFM API 使用示例,这段代码获取了 C 库函数的 radixsort 方法句柄,然后使用它对 Java 数组中的四个字符串进行排序。

// 1. 在C库路径上查找外部函数
Linker linker = Linker.nativeLinker();
SymbolLookup stdlib = linker.defaultLookup();
MethodHandle radixSort = linker.downcallHandle(
                             stdlib.lookup("radixsort"), ...);
// 2. 分配堆上内存以存储四个字符串
String[] javaStrings   = { "mouse", "cat", "dog", "car" };
// 3. 分配堆外内存以存储四个指针
SegmentAllocator allocator = implicitAllocator();
MemorySegment offHeap  = allocator.allocateArray(ValueLayout.ADDRESS, javaStrings.length);
// 4. 将字符串从堆上复制到堆外
for (int i = 0; i < javaStrings.length; i++) {
    // 在堆外分配一个字符串,然后存储指向它的指针
    MemorySegment cString = allocator.allocateUtf8String(javaStrings[i]);
    offHeap.setAtIndex(ValueLayout.ADDRESS, i, cString);
}
// 5. 通过调用外部函数对堆外数据进行排序
radixSort.invoke(offHeap, javaStrings.length, MemoryAddress.NULL, '\0');
// 6. 将(重新排序的)字符串从堆外复制到堆上
for (int i = 0; i < javaStrings.length; i++) {
    MemoryAddress cStringPtr = offHeap.getAtIndex(ValueLayout.ADDRESS, i);
    javaStrings[i] = cStringPtr.getUtf8String(0);
}
assert Arrays.equals(javaStrings, new String[] {"car", "cat", "dog", "mouse"});  // true

JEP 412: Foreign Function & Memory API (Incubator)

JEP 414 - 向量(Vector) API(第二次孵化)

Vector API 最初在 Java 16 孵化并集成,在 Java 17 中进行第二次孵化。这个特性可以让开发人员更方便地使用向量操作来进行数据处理。Vector API 可以提供更高的并行性和更好的性能,从而加速数据处理过程。

// 创建一个 Vector
Vector<Float> v = Vector.of(1.0f, 2.0f, 3.0f, 4.0f);

// 对 Vector 中的元素进行操作
Vector<Float> result = v.map(x -> x * 2).add(Vector.of(1.0f, 1.0f, 1.0f, 1.0f));

// 输出结果
System.out.println(result);

JEP 414: Vector API (Second Incubator)

更多新特性请参考:

JDK 17 – New Features in Java 17

https://openjdk.org/projects/jdk/17/

3. Java 17 升级实战

解决GC毛刺问题——转转搜索推荐服务JDK17升级实践

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

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

相关文章

高校教务系统登录页面JS分析——西安科技大学

高校教务系统密码加密逻辑及JS逆向 本文将介绍高校教务系统的密码加密逻辑以及使用JavaScript进行逆向分析的过程。通过本文&#xff0c;你将了解到密码加密的基本概念、常用加密算法以及如何通过逆向分析来破解密码。 本文仅供交流学习&#xff0c;勿用于非法用途。 一、密码加…

42908-2023 纺织染整助剂产品中有机卤素含量的测定

1 范围 本文件描述了纺织染整助剂产品中有机卤素含量的测定方法。 本文件适用于各类纺织染整助剂中有机卤素含量的测定&#xff0c;包括有机氟、有机氯、有机溴。 2 规范性引用文件 下列文件中的内容通过文中的规范性引用而构成本文件必不可少的条款。其中&#xff0c;注日…

自然语言处理---Transformer模型

Transformer概述 相比LSTM和GRU模型&#xff0c;Transformer模型有两个显著的优势&#xff1a; Transformer能够利用分布式GPU进行并行训练&#xff0c;提升模型训练效率。 在分析预测更长的文本时&#xff0c;捕捉间隔较长的语义关联效果更好。 Transformer模型的作用 基于seq…

香港科技大学广州|先进材料学域博士招生宣讲会—上海专场!!!(暨全额奖学金政策)

香港科技大学广州&#xff5c;先进材料学域博士招生宣讲会—上海专场&#xff01;&#xff01;&#xff01;&#xff08;暨全额奖学金政策&#xff09; “跨学科融合创新&#xff0c;引领新兴与未来行业的突破与发展——先进材料学域” &#xfffd;&#xfffd;&#xfffd;…

深入理解多线程编程和 JVM 内存模型

文章目录 1. 理解进程和线程的概念进程&#xff08;Process&#xff09;线程&#xff08;Thread&#xff09; 2. 理解竞态条件和死锁竞态条件&#xff08;Race Condition&#xff09;死锁&#xff08;Deadlock&#xff09; 3. JVM 内存模型堆&#xff08;Heap&#xff09;栈&am…

正规文法、正规式、确定的有穷自动机DFA、不确定的有穷自动机NFA 的概念、区分以及等价性转换【我直接拿下!】

文章目录 正规文法正规式有穷自动机确定的有穷自动机——DFA不确定的有穷自动机——NFADFA 与 NFA 的区分 正规式转换为正规文法正规文法转换为正规式NFA 转换为 DFANFA 最小化 NFA 转换为正规式正规式转换为 NFA正规文法转换为 NFANFA 转换为正规文法 前言&#xff1a; 在学习…

C语言--程序环境和预处理(宏)

目录 前言 本章重点&#xff1a; 1. 程序的翻译环境和执行环境 2. 详解编译链接 2.1 翻译环境​编辑 2.2 编译本身也分为几个阶段 2.3 运行环境 3. 预处理详解 3.1 预定义符号 3.2 #define 3.2.1 #define 定义标识符 3.2.2 #define 定义宏 2.2.3 #define 替换规则 …

fetch网络请求详解

一&#xff1a;三种常见的网络请求对比&#xff1a; AJAX&#xff1a;基于XMLHttpRequest收发请求&#xff0c;使用较为繁琐&#xff0c;代码量会比较多axios&#xff1a;基于promise的请求客户端&#xff0c;在浏览器和node中均可使用&#xff0c;使用便捷&#xff0c;功能强…

系统设计 - 我们如何通俗的理解那些技术的运行原理 - 第五部分:支付系统

本心、输入输出、结果 文章目录 系统设计 - 我们如何通俗的理解那些技术的运行原理 - 第五部分&#xff1a;支付系统前言如何学习支付系统信用卡为什么被称为“银行最赚钱的产品”&#xff1f;VISA/万事达卡如何赚钱&#xff1f;步骤说明为什么开证行应该得到补偿 当我们在商家…

Linux中的开发工具(yum,vim,gcc/g++,gdb,Makefile,git)

文章目录 1. Linux软件包管理器——yumyum 语法yum 常用命令安装 yum 仓库源 2. Linux编辑器——vimvim 的五种常用模式模式切换vim 基本操作命令模式命令集&#xff08;1&#xff09;光标命令&#xff08;2&#xff09;复制粘贴命令&#xff08;3&#xff09;撤销与重做&#…

深度学习---卷积神经网络

卷积神经网络概述 卷积神经网络是深度学习在计算机视觉领域的突破性成果。在计算机视觉领域。往往输入的图像都很大&#xff0c;使用全连接网络的话&#xff0c;计算的代价较高。另外图像也很难保留原有的特征&#xff0c;导致图像处理的准确率不高。 卷积神经网络&#xff0…

安全多方计算框架最全合集(持续更新)

安全多方计算框架 本文对现有安全多方计算/学习框架进行了全面、系统的梳理。 目前大部分安全多方计算框架主要基于秘密共享、同态加密、混淆电路以及相关基本模块的组合。通常使用定制的协议来支持特定数量的参与方&#xff08;一般为两方或三方&#xff09;&#xff0c;导致…

我发现用StarUML来画UML也挺香的

2023年10月22日&#xff0c;周日晚上 我已经决定以后都用StarUML来画UML了&#xff0c;因为这个软件不仅免费&#xff0c;而且太适合画UML图了 我之前主要用plantUML和draw.io来画UML&#xff0c; plantUML虽然是通过文本来生成UML图&#xff0c;但是排版不是不好看&#xff…

“智能文件批量改名工具:轻松管理文件名,一键去除特殊符号“

你是否曾经在面对一堆文件名中包含特殊符号&#xff0c;而感到困扰&#xff0c;不知道如何快速、准确地处理它们&#xff1f;现在&#xff0c;我们为你带来了一款智能文件批量改名工具&#xff0c;它可以轻松地帮助你去除文件名中的特殊符号&#xff0c;让你的文件管理更加规范…

【试题002】C语言有关于sizeof的使用

1.说明&#xff1a;sizeof()是测量数据类型所占用的内存字节数&#xff0c;字符串常量在存储时除了要存储有效字节外&#xff0c;还要存储一个字符串结束志‘\0’。 2.代码举栗子&#xff1a; #include <stdio.h> int main() {char str[] "book";printf(&qu…

网络协议--Traceroute程序

8.1 引言 由Van Jacobson编写的Traceroute程序是一个能更深入探索TCP/IP协议的方便可用的工具。尽管不能保证从源端发往目的端的两份连续的IP数据报具有相同的路由&#xff0c;但是大多数情况下是这样的。Traceroute程序可以让我们看到IP数据报从一台主机传到另一台主机所经过…

开源LLEMMA发布:超越未公开的顶尖模型,可直接应用于工具和定理证明

深度学习自然语言处理 原创作者&#xff1a;Winnie 今天向大家介绍一个新的开源大语言模型——LLEMMA&#xff0c;这是一个专为数学研究而设计的前沿语言模型。 LLEMMA解数学题的一个示例 LLEMMA的诞生源于在Proof-Pile-2数据集上对Code Llama模型的深度训练。这个数据集是一个…

Java 8 新特性 Ⅱ

方法引用 举例: Integer :: compare 理解: 可以看作是基于lambda表达式的进一步简化 当需要提供一个函数式接口的实例时, 可以使用lambda表达式提供实例 当满足一定条件下, 可以使用方法引用or构造器引用替换lambda表达式 实质: 方法引用作为函数式接口的实例 (注: 需要熟悉…

【AOA-VMD-LSTM分类故障诊断】基于阿基米德算法AOA优化变分模态分解VMD的长短期记忆网络LSTM分类算法(Matlab代码)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…