java18学习笔记
如约而至,JDK 18 于 2022 年 3 月 22 日发布,即Java10之后规定的每半年发布一版
400: | UTF-8 by Default |
408: | Simple Web Server |
413: | Code Snippets in Java API Documentation |
416: | Reimplement Core Reflection with Method Handles |
417: | Vector API (Third Incubator) |
418: | Internet-Address Resolution SPI |
419: | Foreign Function & Memory API (Second Incubator) |
420: | Pattern Matching for switch (Second Preview) |
421: | Deprecate Finalization for Removal |
JEP 400: UTF-8 by Default
将 UTF-8 指定为标准 Java API 的默认字符集。通过这一更改,依赖默认字符集的 API 将在所有实现、操作系统、区域设置和配置中表现一致。
JEP 408: Simple Web Server
简单web服务器见文章 java18学习笔记-Simple Web Server-CSDN博客
JEP 413: Code Snippets in Java API Documentation
为 JavaDoc 的 Standard Doclet 引入 @snippet
标签,以简化在 API 文档中包含示例源代码。
java18学习笔记-JavaDoc的@snippet注释标签-CSDN博客
JEP 416: Reimplement Core Reflection with Method Handles
java.lang.invoke
重新实现了 java.lang.reflect.Method,
Constructor
和 Field
。将方法实现作为反射的底层机制从而降低 java.lang.reflect
和 java.lang.invoke
API 的维护和开发成本
核心反射有两个内部机制用于调用方法和构造器。为了快速启动,它使用 HotSpot 虚拟机中的本地方法来执行特定反射方法或构造器对象的最初几次调用。为了更好的峰值性能,在多次调用后,它会为反射操作生成字节码,并在后续调用中使用该字节码。
JEP 417: Vector API (Third Incubator)
见文章java16学习笔记-Vector API-CSDN博客
JEP 418: Internet-Address Resolution SPI
定义一个主机名和地址解析的服务提供者接口(SPI),以便 java.net.InetAddress
可以使用除平台内置解析器之外的其他解析器。
InetAddress localHost = InetAddress.getLocalHost();String hostAddress = localHost.getHostAddress();String hostName = localHost.getHostName();var address = localHost.getAddress();String canonicalHostName = localHost.getCanonicalHostName();System.out.println("localHost: " + localHost);System.out.println("hostAddress: " + hostAddress);System.out.println("hostName: " + hostName);System.out.println("address: " + address);System.out.println("canonicalHostName: " + canonicalHostName);InetAddress[] allByName = InetAddress.getAllByName("本机");Stream.of(allByName).forEach(System.out::println);
JEP 419: Foreign Function & Memory API (Second Incubator)
见文章Foreign-Memory Access API外部内存API -CSDN博客
JEP 420: Pattern Matching for switch (Second Preview)
见文章java17学习笔记-switch总结-CSDN博客
JEP 421: Deprecate Finalization for Removal
在未来的版本中弃用终结以供移除。目前终结仍然默认启用,但可以禁用以促进早期测试。在未来的版本中它将默认禁用,在更后的版本中它将被移除。依赖终结的库和应用程序的维护者应考虑迁移到其他资源管理技术,如 try
-with-resources 语句和清理器
弃用 try-finally
假设有好几个流try中没有正常关闭,到finally中关闭的时候第一个关闭又抛了异常,那后面的流全都会泄露。java7就引入了try-with-resources,自动关闭实现了 AutoCloseable
或 Closeable
接口的资源(如文件流、数据库连接等),利用try-with-resources可以避免资源泄漏。
弃用标准 Java API 中的终结器
终结化是在 Java 1.0 中引入的,旨在帮助避免资源泄漏。一个类可以声明一个终结化方法——即 protected void finalize()
方法——其主体释放任何底层资源。GC 将在回收不可达对象内存之前调度该对象的终结化方法被调用;反过来, finalize
方法可以执行诸如调用对象的 close
方法等操作。
乍一看,这似乎是一个有效的安全网,用于防止资源泄漏:如果一个包含未关闭资源的对象变得不可达(上述的 input
对象),那么 GC 将安排调用终结器,终结器将关闭该资源。实际上,终结器将垃圾回收的权力用于管理非内存资源(Barry Hayes,《收集器接口中的终结器》,1992 年国际内存管理研讨会)。
终结器的缺陷
不可预测的延迟——一个对象变得不可达和其终结器被调用之间可能经过任意长的时间。事实上,GC 不保证任何终结器会被调用。
无约束的行为——终结器代码可以执行任何操作。特别是,它可以保存正在被终结的对象的引用,从而复活该对象,使其再次变得可达。
始终启用——终结化没有显式的注册机制。带有终结器的类为该类的每个实例启用终结化,无论是否需要。对象的终结化无法取消,即使它不再对该对象有必要。
未指定的线程——终结化在未指定的线程上以任意顺序运行。线程和顺序均无法控制。
这些缺陷早在二十多年前就被广泛认识。早在 1998 年就出现了关于谨慎使用 Java 终结化的建议(Bill Venners,《对象终结化和清理:如何设计类以进行正确的对象清理》,JavaWorld,1998 年 5 月),并在 Joshua Bloch 2001 年的著作《Effective Java》(第 6 条:“避免终结化”)中重点提及。自 2008 年以来,SEI CERT Oracle Java 编码标准已建议不使用终结化。
弃用标准 Java API 中的终结器
java.lang.Object.finalize()
java.lang.Enum.finalize()
java.awt.Graphics.finalize()
java.awt.PrintJob.finalize()
java.util.concurrent.ThreadPoolExecutor.finalize()
javax.imageio.spi.ServiceRegistry.finalize()
javax.imageio.stream.FileCacheImageInputStream.finalize()
javax.imageio.stream.FileImageInputStream.finalize()
javax.imageio.stream.FileImageOutputStream.finalize()
javax.imageio.stream.ImageInputStreamImpl.finalize()
javax.imageio.stream.MemoryCacheImageInputStream.finalize()
- (
java.awt.**
中的另外三个终结器已经被最终弃用,并且独立于这个 JEP 从 Java 18 中移除。)