JAVA版本及其新功能和特性
2022-09-29 13:51:45 0 举报
AI智能生成
JAVA版本及其新功能和特性
作者其他创作
大纲/内容
2017 年 9 月 22 日
JPMS(Java Platform Module System)是Java 9发行版的核心亮点。它也被称为Jigshaw项目。模块是新的结构,就像我们已经有包一样。使用新的模块化编程开发的应用程序可以看作是交互模块的集合,这些模块之间具有明确定义的边界和依赖关系。JPMS包括为编写模块化应用程序提供支持,以及将JDK源代码模块化。JDK 9 附带了大约 92 个模块(在 GA 版本中可以进行更改)。Java 9 Module System有一个\"java.base\"模块。它被称为基本模块。它是一个独立的模块,不依赖于任何其他模块。默认情况下,所有其他模块都依赖于\"java.base\"。在java模块化编程中:一个模块通常只是一个 jar 文件,在根目录下有一个文件module-info.class。要使用模块,请将 jar 文件包含到modulepath而不是classpath. 添加到类路径的模块化 jar 文件是普通的 jar 文件,module-info.class文件将被忽略。典型的module-info.java类如下所示:module helloworld { exports cn.dayangshuo.demo;}module test { requires helloworld;}
模块系统
JShell是JDK 9发行版 [ JEP 222 ]附带的新命令行交互式工具,用于评估用 Java 编写的声明、语句和表达式。JShell 允许我们执行 Java 代码片段并立即获得结果,而无需创建解决项目。Jshell 很像我们在 linux 操作系统中的命令窗口。不同之处在于 JShell 是特定于 Java 的。除了执行简单的代码片段之外,它还有许多其他功能,例如:在单独的窗口中启动内置代码编辑器在单独的窗口中启动你选择的代码编辑器在这些外部编辑器中发生保存操作时执行代码从文件系统加载预先编写的类
JShell – REPL 工具
HTTP/1.1 客户端于 1997 年发布。此后发生了很多变化。因此,Java 9 引入了新的 API,它使用起来更干净、更清晰,并且还增加了对 HTTP/2 的支持。新 API 使用 3 个主要类HttpClient,HttpRequest和HttpResponse.要发出请求,就像获取客户端、构建请求并发送它一样简单,示例:HttpClient httpClient = HttpClient.newHttpClient(); HttpRequest httpRequest = HttpRequest.newBuilder().uri(new URI(\"https://baidu.com/\
HTTP 2 客户端
Java 9 增强了javadoc生成 HTML5 标记的工具。它目前以 HTML 4.01 生成页面。为了生成 HTML5 Javadoc,参数-html5需要放在命令行参数中。要在命令行上生成文档,你将运行:javadoc [选项] [包名] [源文件] [@files]使用 HTML5 可以带来更简单的 HTML5 结构的好处。它还实现了可访问性的WAI-ARIA 标准。这旨在使身体或视觉障碍的人更容易使用屏幕阅读器等工具访问 javadocs 页面。JEP 225提供了在 javadoc 中搜索程序元素和标记的单词和短语的能力。以下内容将被索引和搜索:模块的声明名称套餐类型和成员方法参数类型的简单名称这是在客户端实现的,带有一个新的search.jsJavascript 文件,以及生成 javadoc 时生成的索引。生成的 HTML5 API 页面上有一个搜索框。请注意,默认情况下会添加搜索选项,但可以使用参数关闭:-noindex。
改进的 Javadoc
此增强与如何将应用程序类打包到 jar 文件中有关。以前,开发者必须将所有类打包到一个 jar 文件中,然后放入希望使用它的另一个应用程序的类路径中。使用多版本特性,现在一个 jar 可以包含一个类的不同版本——兼容不同的 JDK 版本。关于一个类的不同版本,以及加载的类应该选择哪个类的JDK版本的信息存储在MANIFEST.MF文件中。在这种情况下,文件在其主要部分中MANIFEST.MF包含该条目Multi-Release: true此外,META-INF 包含一个版本子目录,其以整数命名的子目录——从 9 开始(对于 Java 9)——存储特定于版本的类和资源文件。例如JAR content root A.class B.class C.class D.class META-INF MANIFEST.MF versions 9 A.class B.class假设在 JDK 10 A.class中更新为利用一些 Java 10 新特性,那么这个 Jar 文件可以像这样更新:JAR content root A.class B.class C.class D.class META-INF MANIFEST.MF versions 9 A.class B.class 10 A.class它看起来非常有希望解决在大型应用程序中经常看到的依赖地狱,其中不同版本的 jar 彼此不兼容。此功能可以为解决这些情况提供很大帮助。
多版本兼容 JAR 包
直到Java 8,@SafeVarargs才能在静态方法、final方法和构造器上使用。但是这些方法或者构造器是不能被覆盖的。这些方法中缺少另一个不能被覆盖的方法,这个方法就是私有方法。Java 9可以将@SafeVarargs添加到私有方法上。下面的例子在Java 9中是正确的,但是在Java 8中就会抛出编译时错误: 注释@SafeVarargs不能在非final的实例方法iAmSafeVaragrsMethod上使用。
注释SafeVarargs范围的延伸
List,Set 和 Map 接口中,新的静态工厂方法可以创建这些集合的不可变实例。
集合工厂方法
私有接口方法
在 Java 5 之前,生成新进程的唯一方法是使用该Runtime.getRuntime().exec()方法。然后在 Java 5 中,ProcessBuilder引入了 API,它支持一种更简洁的方式来生成新进程。现在,Java 9 添加了一种获取有关当前进程和任何衍生进程的信息的新方法。要获取任何进程的信息,现在您应该使用java.lang.ProcessHandle.Info接口。此界面可用于获取大量信息,例如:用于启动进程的命令命令的参数进程开始的时刻它和创建它的用户花费的总时间ProcessHandle processHandle = ProcessHandle.current();ProcessHandle.Info processInfo = processHandle.info();System.out.println(processHandle.getPid());System.out.println(processInfo.arguments().isPresent());System.out.println(pprocessInfo.command().isPresent());System.out.println(processInfo.command().get().contains(\"java\
进程 API
从 Java 9 开始,您可以使用新的工厂方法创建不可变集合,例如不可变list、不可变set和不可变map。例如:import java.util.List;public class ImmutableCollections { public static void main(String[] args) { List<String> namesList = List.of(\"Lokesh\
Collection(集合) API更新
Java 9 引入了两种与 Streams 交互的新方法,即takeWhile/dropWhile方法。此外,它还添加了两个重载方法,即ofNullable和iterate方法。新方法takeWhile。dropWhile允许开发者基于谓词获取流的一部分在有序流上,takeWhile返回从流中获取的与给定谓词匹配的元素的“最长前缀”,从流的开头开始。dropWhile返回与 不匹配的剩余项目takeWhile。在无序流上,takeWhile返回与给定谓词(但不是全部)匹配的流元素的子集,从流的开头开始。dropWhile在删除与给定谓词匹配的元素子集后返回剩余的流元素。List<String> alphabets = List.of(\"a\
Stream(流) API改进
改进 try-with-resources
从 Java 9 开始,@Deprecated注解将具有两个属性,即forRemoval和since.forRemoval – 指示带注释的元素是否会在未来版本中被删除。since - 它返回注释元素被弃用的版本。强烈建议使用 @deprecated javadoc 标记在文档中解释弃用程序元素的原因。如果适用,文档还应建议并链接到推荐的替代 API。替换 API 通常具有微妙不同的语义,因此也应讨论此类问题。
改进的弃用注解 @Deprecated
匿名类可以使用钻石操作符(Diamond Operator)。
改进钻石操作符(Diamond Operator)
java.util.Optional 添加了很多新的有用方法,Optional 可以直接转为 stream。
改进 Optional 类
定义多分辨率图像API,开发者可以很容易的操作和展示不同分辨率的图像了。
多分辨率图像 API
CompletableFuture 类的异步机制可以在 ProcessHandle.onExit 方法退出时执行操作。
改进的 CompletableFuture API
内置了一个轻量级的JSON API
轻量级的 JSON API
Java 9中引入了新的响应式流 API 来支持 Java 9 中的响应式编程。
响应式流(Reactive Streams) API
JDK 9 通过新的日志记录 API 改进了平台类(JDK 类)和 JVM 组件中的日志记录。它允许开发者指定自己选择的日志记录框架(例如Log4J2)作为日志记录工具,用于记录来自 JDK 类的消息。关于这个 API,你应该知道几件事:API 旨在供 JDK 中的类使用,而不是由应用程序类使用。对于应用程序代码,开发者将像以前一样继续使用其他日志记录 API。API 不允许开发者以编程方式配置记录器。API 由以下部分组成:服务接口,java.lang.System.LoggerFinder是一个抽象静态类java.lang.System.Logger提供日志记录 API 的接口getLogger()类中的一个重载方法java.lang.System,它返回一个记录器实例。JDK 9 还添加了一个新的命令行选项 ,-Xlog它使开发者可以单点访问从 JVM 的所有类记录的所有消息。以下是使用该-Xlog选项的语法:-Xlog[:][:[][:[][:]]]所有选项都是可选的。如果缺少前面的部分,-Xlog则必须为该部分使用冒号。例如,-Xlog::stderr表示所有部分都是默认的,输出设置为stderr.
平台和 JVM 日志记录
新特性
9
2018年3月21日
Java 现在有var声明。它允许开发者在不指定其类型的情况下声明局部变量。变量的类型将从创建的实际对象的类型中推断出来。
var关键字(局部变量类型推断)
在早期的 JDK 结构中,组成垃圾收集器 (GC) 实现的组件分散在代码库的各个部分。它在 Java 10 中发生了变化。现在,它是 JVM 源代码中的一个干净的接口,允许快速轻松地集成替代收集器。它将改善不同垃圾收集器的源代码隔离。
垃圾收集器接口
Java 9 引入了 G1(垃圾优先)垃圾收集器。G1 垃圾收集器旨在避免完全收集,但是当并发收集无法足够快地回收内存时。通过此更改,将发生回退完整 GC。G1 的完整 GC 的当前实现使用单线程标记-扫描-紧凑算法。此更改将并行化 mark-sweep-compact 算法并使用相同数量的线程。当收集的并发线程无法足够快地恢复内存时,它将被触发。线程数可以通过-XX:ParallelGCThreads选项来控制。
G1 的并行全 GC
此更改的目标是使 HotSpot VM 能够在用户指定的备用内存设备(例如 NV-DIMM)上分配 Java 对象堆。要在此类内存中分配堆,我们可以添加一个新选项-XX:AllocateHeapAt=<path>. 此选项将获取文件系统的路径并使用内存映射来实现在内存设备上分配对象堆的预期结果。现有的与堆相关的标志,如-Xmx、-Xms等,以及与垃圾收集相关的标志将继续像以前一样工作。
替代存储设备上的堆分配
作为此更改的一部分,JDK 库的众多存储库被合并到一个存储库中,以简化和简化开发。在 JDK 9 中有八个存储库:root、corba、hotspot、jaxp、jaxws、jdk、langtools和nashorn. 在统一的林中,Java 模块的代码通常组合在一个顶级src目录下。例如,今天在 JDK 林中有基于模块的目录,如$ROOT/jdk/src/java.base...$ROOT/langtools/src/java.compiler...在合并的库中,此代码改为组织为-$ROOT/src/java.base$ROOT/src/java.compiler...
将 JDK库整合到单个存储库中
此功能的目标是改善启动足迹,扩展现有的类数据共享 (“CDS”) 功能以允许将应用程序类放置在共享存档中。JDK 5 中引入的类数据共享允许将一组类预处理为共享存档文件,然后可以在运行时进行内存映射以减少启动时间。当多个 JVM 共享同一个归档文件时,它还可以减少动态内存占用。目前 CDS 只允许引导类加载器加载归档类。应用程序 CDS 允许内置系统类加载器、内置平台类加载器和自定义类加载器加载归档类。指定-XX:+UseAppCDS命令行选项以启用系统类加载器、平台类加载器和其他用户定义的类加载器的类数据共享。
应用程序类-数据共享
cacerts 密钥库是 JDK 的一部分,旨在包含一组根证书,可用于在各种安全协议中使用的证书链中建立信任。然而,JDK 源代码中的 cacerts 密钥库目前是空的。cacerts 密钥库将填充一组由 Oracle 的 Java SE 根 CA 程序的 CA 颁发的根证书。许多供应商已经签署了所需的协议,并且每个供应商都将包含一份根证书列表。未签署协议的将不包括在内。那些需要更长时间处理的将包含在下一个版本中。这也意味着 Oracle 和 Open JDK 二进制文件在功能上是相同的。TLS 等关键安全组件将默认在未来的 OpenJDK 构建中工作。
根证书
此功能使基于 Java 的 JIT 编译器Graal可以用作 Linux/x64 平台上的实验性 JIT 编译器。Graal 将使用 JDK 9 中引入的 JVM 编译器接口 (JVMCI)。Graal 已经在 JDK 中,因此将其作为实验性 JIT 启用将主要是测试和调试工作。要启用 Graal 作为 JIT 编译器,请在 java 命令行上使用以下选项:-XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompilerGraal 是从头开始用 Java 完全重写 JIT 编译器。以前的 JIT 编译器是用 C++ 编写的。
基于 Java 的 JIT 编译器(实验性)
这个 JEP 为提高 VM 性能奠定了基础,它可以在应用程序线程上执行回调,而无需执行全局 VM 安全点。这意味着 JVM 可以停止单个线程,而不仅仅是所有线程。线程本地握手最初将在 x64 和 SPARC 上实现。其他平台将退回到正常的安全点。一个新的产品选项-XX:ThreadLocalHandshakes(默认值true)允许用户在支持的平台上选择正常的安全点。
Thread-Local握手
10
2018 年 9 月
Java 使用HttpURLConnection进行HTTP通信已经很长一段时间了。但随着时间的推移,要求变得越来越复杂,应用程序的要求也越来越高。在 Java 11 之前,开发人员不得不求助于功能丰富的库,如Apache HttpComponents或OkHttp等。我们看到Java 9发布包含一个HttpClient实现作为实验性功能。它随着时间的推移而发展,现在是 Java 11 的最终功能。现在 Java 应用程序可以进行 HTTP 通信,而无需任何外部依赖。
HTTP客户端API
传统上,对于我们想要执行的每个程序,我们都需要先编译它。对于用于测试目的的小程序来说,这似乎是不必要的冗长过程。Java 11 改变了它,现在我们可以执行包含在单个文件中的 Java 源代码,而无需先编译它。$java HelloWorld.java
无需编译即可启动单文件程序
String.repeat(Integer)String.isBlank()String.strip()String.lines()
字符串API更新
在 Java 11 之前,将集合转换为数组并不简单。Java 11 使转换更加方便。public class HelloWorld { public static void main(String[] args) { List<String> names = new ArrayList<>(); names.add(\"alex\"); names.add(\"brian\"); names.add(\"charles\"); String[] namesArr1 = names.toArray(new String[names.size()]); //Java 11之前 String[] namesArr2 = names.toArray(String[]::new); //Java 11 }}
Collection.toArray
使用这些重载方法,Java 11 旨在减少大量样板代码,从而更容易读取和写入文件。public class HelloWorld { public static void main(String[] args) { //读取文件内容为字符串 URI txtFileUri = getClass().getClassLoader().getResource(\"helloworld.txt\
Files.readString() 和 Files.writeString()
Optional是一个容器对象,它可能包含也可能不包含非空值。如果不存在任何值,则该对象被认为是空的。isPresent()方法如果值存在则返回true,否则返回false。isEmpty()方法与isPresent()方法相反,如果存在值则返回false,否则返回true。所以我们无论如何都不要写否定条件。适当时使用这两种方法中的任何一种。public class HelloWorld { public static void main(String[] args) { String currentTime = null; assertTrue(!Optional.ofNullable(currentTime).isPresent()); assertTrue(Optional.ofNullable(currentTime).isEmpty()); currentTime = \"12:00 PM\"; assertFalse(!Optional.ofNullable(currentTime).isPresent()); assertFalse(Optional.ofNullable(currentTime).isEmpty()); }}
Optional.isEmpty()
11
2019 年 3 月 19 日
Stream API 中的 Collectors.teeing()
字符串缩进
transform
字符串常量
字符串 API 变更
有时,我们想确定两个文件是否具有相同的内容。此 API 有助于比较文件的内容。mismatch()方法比较两个文件路径并返回一个long值。long 表示两个文件内容中第一个不匹配字节的位置。'–1'如果文件“相等”,则返回值。Path helloworld1 = tempDir.resolve(\"helloworld1.txt\"); Path helloworld2 = tempDir.resolve(\"helloworld2.txt\
紧凑数字格式
支持 Unicode 11
12
2019 年 9 月 17 日
使用yield,我们现在可以有效地从 switch 表达式返回值,并能够更容易实现策略模式。package cn.dayangshuo.collectors;/** * @author DAYANG */public class SwitchTest { public static void main(String[] args) { var me = 4; var operation = \"平方\"; var result = switch (operation) { case \"加倍\" -> { yield me * 2; } case \"平方\" -> { yield me * me; } default -> me; }; System.out.println(result); }}
switch表达式改进
第二个预览功能是多行String的文本块,例如嵌入的 JSON、XML、HTML 等。早些时候,为了在我们的代码中嵌入 JSON,我们将其声明为字符串文字:String JSON_STRING = \"{\\\" + \"\\\"name\\\" : \\\"Baeldung\\\
文本块改进
一段时间以来,类数据共享 (CDS) 一直是 Java HotSpot VM 的一个突出特性。它允许在不同的 JVM 之间共享类元数据,以减少启动时间和内存占用。JDK 10 通过添加应用程序 CDS ( AppCDS ) 扩展了这种能力——让开发人员能够在共享存档中包含应用程序类。JDK 12 进一步增强了这个特性,默认包括 CDS 归档。但是,归档应用程序类的过程很繁琐。要生成存档文件,开发人员必须先试运行他们的应用程序以创建类列表,然后将其转储到存档中。之后,该存档可用于在 JVM 之间共享元数据。通过动态归档,JDK 13 简化了这个过程。现在我们可以在应用程序退出时生成一个共享存档。这消除了试运行的需要。要使应用程序能够在默认系统存档之上创建动态共享存档,我们需要添加一个选项-XX:ArchiveClassesAtExit并将存档名称指定为参数:java -XX:ArchiveClassesAtExit=<archive filename> -cp <app jar> AppName然后,我们可以使用新创建的存档通过-XX:SharedArchiveFile选项运行相同的应用程序:java -XX:SharedArchiveFile=<archive filename> -cp <app jar> AppName
动态CDS档案
Java 11 中引入了ZGC作为低延迟垃圾收集机制,因此 GC 暂停时间从未超过 10 毫秒。但是,与 G1 和 Shenandoah 等其他 HotSpot VM GC 不同,它没有配备将未使用的堆内存返回给操作系统的功能。我们现在减少了内存占用并提高了性能。从 Java 13 开始,ZGC 现在默认将未提交的内存返回给操作系统,直到达到指定的最小堆大小。如果我们不想使用此功能,我们可以通过以下方式回到 Java 11 方式:使用选项-XX:-ZUncommit,或设置相等的最小 ( -Xms ) 和最大 ( -Xmx ) 堆大小此外,ZGC 现在支持的最大堆大小为 16TB。早些时候,限制到4TB 。
ZGC:取消提交未使用的内存
自 Java 出现以来,我们已经将 Socket(java.net.Socket和java.net.ServerSocket)API 视为 Java 不可或缺的一部分。然而,在过去的二十年里,它们从未现代化。它们是用遗留的 Java 和 C 编写的,既麻烦又难以维护。Java 13 逆势而上,取代了底层实现,使 API 与未来的用户模式线程保持一致。提供者接口现在指向NioSocketImpl而不是PlainSocketImpl。这个新编码的实现基于与java.nio相同的内部基础结构。同样,我们确实有办法回到使用PlainSocketImpl*。我们可以通过将系统属性-Djdk.net.usePlainSocketImpl设置为true来启动 JVM,以使用较旧的实现。默认值为*NioSocketImpl。
重新实现 Legacy Socket API
其他
13
2020 年 3 月 17 日
package cn.dayangshuo.collectors;/** * @author DAYANG */public class NullPointerExceprionsTest { //空指针报错 public static void main(String[] args) { User user = null; System.out.println(user.getName()); } static class User{ private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }}//jdk8的报错信息:Exception in thread \"main\" java.lang.NullPointerException at cn.dayangshuo.collectors.NullPointerExceprionsTest.main(NullPointerExceprionsTest.java:9)//jdk14的报错信息: Exception in thread \"main\" java.lang.NullPointerException: Cannot invoke \"cn.dayangshuo.collectors.NullPointerExceprionsTest$User.getName()\" because \"user\" is null at cn.dayangshuo.collectors.NullPointerExceprionsTest.main(NullPointerExceprionsTest.java:9)
NullPointerExceptions:精确描述哪个变量是null
14
2020 年 9 月 15 日
EdDSA (Edwards-Curve Digital Signature Algorithm) 是在 Java 15 中通过JEP 339添加的另一种附加数字签名方案。与其他可用的签名方案相比,它提供了更好的性能和安全的签名。import java.nio.charset.StandardCharsets;import java.security.KeyPair;import java.security.KeyPairGenerator;import java.security.Signature;import java.util.Base64;/** * @author DAYANG */public class EdDSATest { public static void main(String[] args) throws Exception { KeyPairGenerator kpg = KeyPairGenerator.getInstance(\"Ed25519\"); KeyPair kp = kpg.generateKeyPair(); byte[] msg = \"dayang\".getBytes(StandardCharsets.UTF_8); Signature sig = Signature.getInstance(\"Ed25519\"); sig.initSign(kp.getPrivate()); sig.update(msg); byte[] s = sig.sign(); String encodedString = Base64.getEncoder().encodeToString(s); System.out.println(encodedString); }}
EdDSA 算法
隐藏类不同于普通的 Java 类。它们不能被其他类的字节码直接使用。隐藏类旨在供在运行时生成类并通过反射间接使用它们的框架使用。使用隐藏类,不是框架开发人员可以创建外部类看不到的不可发现的类;并且可以显式卸载,而不必担心来自其他类的可能引用。JVM 支持主动卸载不可发现的类,因此框架可以灵活地定义任意数量的类。
隐藏类
15
2021 年 3 月 16 日
DateTimeFormatter的新增功能,可以表示一天中的时段,例如“上午”、“下午”package cn.dayangshuo.collectors;import java.time.LocalTime;import java.time.format.DateTimeFormatter;/** * @author DAYANG */public class DateTimeTest { public static void main(String[] args) { String date1 = DateTimeFormatter.ofPattern(\"a\").format(LocalTime.now()); String date2 = DateTimeFormatter.ofPattern(\"B\").format(LocalTime.now()); String date3 = DateTimeFormatter.ofPattern(\"k\").format(LocalTime.now()); System.out.println(date1); System.out.println(date2); System.out.println(date3); }}//下午//下午//17
时段支持
现在我们可以使用Collectors.toList 和Collectors.toSet来减少一些模板代码:List<String> integersAsString = Arrays.asList(\"1\
添加Stream.toList方法
之前:Object obj = \"大阳\";if (obj instanceof String) { String t = (String) obj; // TODO}现在:Object obj = \"大阳\";if (obj instanceof String t) { // TODO}
instanceof的模式匹配
16
2021年9月
传统的Java应用程序通过创建一个类,通过该类的构造方法实例化类,并通过getter和setter方法访问成员变量或者设置成员变量的值。有了record关键字,你的代码会变得更加简洁。package cn.dayangshuo;/** * 普通的dto * @author DAYANG */public class NormalEntity { public static void main(String[] args) { //传统的方式 User1 user1 = new User1(\"大阳\
record纪录类(标准版)
从JDK8到JDK17陆续增加了更多字符串方法,操作字符串更简单了。isBlank():如果字符串为空或字符串仅包含空格(包括制表符),则返回 true。注意与isEmpty() 不同,isEmpty()仅在长度为 0 时返回 true。lines():将字符串拆分为字符串流,每个字符串包含一行。strip() : 分别从开头和结尾;stripLeading()/stripTrailing()仅开始和仅结束删除空格。repeat(int times):返回一个字符串,该字符串采用原始字符串并按指定的次数重复该字符串。readString():允许从文件路径直接读取到字符串。writeString(Path path):将字符串直接写入指定路径处的文件。indent(int level):缩进字符串的指定量。负值只会影响前导空格。transform(Function f):将给定的 lambda 应用于字符串。
新的字符串方法
package cn.dayangshuo;/** * @author DAYANG */public class OldSwitch { public static void main(String[] args) { oldSwitch(); newSwitch(); } private static void oldSwitch() { int size = 3; String cn = \"\"; switch (size) { case 1: cn = \"壹\"; break; case 2: cn = \"贰\"; break; case 3: cn = \"叁\"; break; default: cn = \"未知\"; } System.out.println(cn); } //更清爽 private static void newSwitch() { int size = 3; String cn = switch (size) { case 1 -> \"壹\"; case 2 -> \"贰\
switch表达式
Java处理json或者xml文本时,需要多个繁琐的嵌套转义,代码写着费劲,维护更费劲。从Java13开始引入了文本块(Text blocks),上代码: package cn.dayangshuo; /** * @author DAYANG */ public class TextBlocks { public static void main(String[] args) { //需要转义 String jsonStr = \"{\\\"name\\\": \\\"大阳\\\"}\"; //文本块,不需要转义字符 String textBlocks = \"\"\" {\"name\": \"大阳\"} \"\"\"; System.out.println(jsonStr); System.out.println(textBlocks); } }
文本块
密封的类和接口限制了其他类或接口可以扩展或实现它们public sealed interface Shape{ final class Planet implements Shape {} final class Star implements Shape {} final class Comet implements Shape {}}public abstract sealed class Test{ final class A extends Test {} final class B extends Test {} final class C extends Test {}}
密封类(Sealed classes)
既然是恢复严格的浮点语义,那么说明在某个时间点之前,是始终严格的浮点语义的。其实在 Java SE 1.2 之前,所有的浮点计算都是严格的,但是以当初的情况来看,过于严格的浮点计算在当初流行的 x86 架构和 x87 浮点协议处理器上运行,需要大量的额外的指令开销,所以在 Java SE 1.2 开始,需要手动使用关键字 strictfp(strict float point) 才能启用严格的浮点计算。但是在 2021 年的今天,硬件早已发生巨变,当初的问题已经不存在了,所以从 Java 17 开始,恢复了始终严格的浮点语义这一特性。扩展:strictfp 是 Java 中的一个关键字,大多数人可能没有注意过它,它可以用在类、接口或者方法上,被 strictfp 修饰的部分中的 float 和 double 表达式会进行严格浮点计算。下面是一个示例,其中的 testStrictfp() 被 strictfp 修饰。package com.wdbyte;public class Main { public static void main(String[] args) { testStrictfp(); } public strictfp static void testStrictfp() { float aFloat = 0.6666666666666666666f; double aDouble = 0.88888888888888888d; double sum = aFloat + aDouble; System.out.println(\"sum: \" + sum); }}
恢复始终严格的浮点语义
为伪随机数生成器 RPNG(pseudorandom number generator)增加了新的接口类型和实现,让在代码中使用各种 PRNG 算法变得容易许多。这次增加了 RandomGenerator 接口,为所有的 PRNG 算法提供统一的 API,并且可以获取不同类型的 PRNG 对象流。同时也提供了一个新类 RandomGeneratorFactory 用于构造各种 RandomGenerator 实例,在 RandomGeneratorFactory 中使用 ServiceLoader.provider 来加载各种 PRNG 实现。下面是一个使用示例:随便选择一个 PRNG 算法生成 5 个 10 以内的随机数。package com.wdbyte.java17;import java.util.Date;import java.util.random.RandomGenerator;import java.util.random.RandomGeneratorFactory;import java.util.stream.Stream;/** * @author niulang */public class JEP356 { public static void main(String[] args) { RandomGeneratorFactory<RandomGenerator> l128X256MixRandom = RandomGeneratorFactory.of(\"L128X256MixRandom\"); // 使用时间戳作为随机数种子 RandomGenerator randomGenerator = l128X256MixRandom.create(System.currentTimeMillis()); for (int i = 0; i < 5; i++) { System.out.println(randomGenerator.nextInt(10)); } }}得到输出:73446你也可以遍历出所有的 PRNG 算法。RandomGeneratorFactory.all().forEach(factory -> { System.out.println(factory.group() + \":\" + factory.name());});得到输出:LXM:L32X64MixRandomLXM:L128X128MixRandomLXM:L64X128MixRandomLegacy:SecureRandomLXM:L128X1024MixRandomLXM:L64X128StarStarRandomXoshiro:Xoshiro256PlusPlusLXM:L64X256MixRandomLegacy:RandomXoroshiro:Xoroshiro128PlusPlusLXM:L128X256MixRandomLegacy:SplittableRandomLXM:L64X1024MixRandom可以看到 Legacy:Random 也在其中,新的 API 兼容了老的 Random 方式,所以你也可以使用新的 API 调用 Random 类生成随机数。// 使用 RandomRandomGeneratorFactory<RandomGenerator> l128X256MixRandom = RandomGeneratorFactory.of(\"Random\");// 使用时间戳作为随机数种子RandomGenerator randomGenerator = l128X256MixRandom.create(System.currentTimeMillis());for (int i = 0; i < 5; i++) { System.out.println(randomGenerator.nextInt(10));}
增强的伪随机数生成器
如 Java 16 的 JEP 396 中描述的一样,为了提高 JDK 的安全性,使 --illegal-access 选项的默认模式从允许更改为拒绝。通过此更改,JDK 的内部包和 API(关键内部 API 除外)将不再默认打开。但是在 Java 17 中,除了 sun.misc.Unsafe ,使用 --illegal-access 命令也不能打开 JDK 内部的强封装模式了,除了 sun.misc.Unsafe API .在 Java 17 中使用 --illegal-access 选项将会得到一个命令已经移除的警告。➜ bin ./java -versionopenjdk version \"17\
更强的 JDK 内部封装
在 Java 9 的 JEP 295 中,引入了实验性的提前编译 jaotc 工具,但是这个特性自从引入依赖用处都不太大,而且需要大量的维护工作,所以在 Java 17 中决定删除这个特性。主要移除了三个 JDK 模块:jdk.aot - jaotc 工具。Jdk.internal.vm.compiler - Graal 编译器。jdk.internal.vm.compiler.management同时也移除了部分与 AOT 编译相关的 HotSpot 代码:src/hotspot/share/aot — dumps and loads AOT codeAdditional code guarded by #if INCLUDE_AOT
移除实验性的 AOT 和 JIT 编译器
Security Manager 在 JDK 1.0 时就已经引入,但是它一直都不是保护服务端以及客户端 Java 代码的主要手段,为了 Java 的继续发展,决定弃用 Security Manager,在不久的未来进行删除。@Deprecated(since=\"17\
弃用 Security Manager
指定上下文的反序列化过滤器
使用新的 macOS 渲染库
支持 macOS/AArch64 架构
删除已弃用的 Applet API
移除 RMI Activation
17(LTS)
JAVA版本
0 条评论
回复 删除
下一页