Java 18 在 2022 年 3 月 22 日正式发布,Java 18 不是一个长期支持版本,这次更新共带来 9 个新功能。

OpenJDK Java 18 下载:https://jdk.java.net/18/

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

JEP 描述
JEP 400 默认为 UTF-8 [1]
JEP 408 简单的网络服务器 [2]
JEP 413 Java API 文档中的代码片段 [3]
JEP 416 使用方法句柄重新实现核心反射 [4]
JEP 417 Vector API(三次孵化)[5]
JEP 418 互联网地址解析 SPI [6]
JEP 419 Foreign Function & Memory API (二次孵化)[7]
JEP 420 switch 模式匹配(二次预览)[8]
JEP 421 弃用完成删除 [9]

JEP 400:默认 UTF-8 字符编码

JDK 一直都是支持 UTF-8 字符编码,这次是把 UTF-8 设置为了默认编码,也就是在不加任何指定的情况下,默认所有需要用到编码的 JDK API 都使用 UTF-8 编码,这样就可以避免因为不同系统,不同地区,不同环境之间产生的编码问题。

Mac OS 默认使用 UTF-8 作为默认编码,但是其他操作系统上,编码可能取决于系统的配置或者所在区域的设置。如中国大陆的 windows 使用 GBK 作为默认编码。很多同学初学 Java 时可能都遇到过一个正常编写 Java 类,在 windows 系统的命令控制台中运行却出现乱码的情况。

使用下面的命令可以输出 JDK 的当前编码。

# Mac 系统,默认 UTF-8
➜  ~ java -XshowSettings:properties -version 2>&1 | grep file.encodingfile.encoding = UTF-8file.encoding.pkg = sun.io
➜  ~

下面编写一个简单的 Java 程序,输出默认字符编码,然后输出中文汉字 ” 你好 “,看看 Java 18 和 Java 17 运行区别。

系统环境:Windows 11

import java.nio.charset.Charset;public class Hello{public static void main(String[] args) {System.out.println(Charset.defaultCharset());System.out.println("你好");}
}

从下面的运行结果中可以看到,使用 JDK 17 运行输出的默认字符编码是 GBK,输出的中文 ” 你好 “已经乱码了。乱码是因为 VsCode 默认的文本编辑器编码是 UTF-8,而中国地区的 Windows 11 默认字符编码是 GBK,也是 JDK 17 默认获取到的编码。所以会在控制台输出时乱码;而使用 JDK 18 输出的默认编码就是 UTF-8,所以可以正常的输出中文” 你好 “。

JEP 408:简单的 Web 服务器

在 Java 18 中,提供了一个新命令 jwebserver,运行这个命令可以启动一个简单的 、最小化的静态 Web 服务器,它不支持 CGI 和 Servlet,所以最好的使用场景是用来测试、教育、演示等需求。

其实在如 Python、Ruby、PHP、Erlang 等许多平台都提供了开箱即用的 Web 服务器,可见一个简单的 Web 服务器是一个常见的需求,Java 一直没有这方面的支持,现在可以了。

在 Java 18 中,使用 jwebserver 启动一个 Web 服务器,默认发布的是当前目录。

在当前目录创建一个网页文件 index.html

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<h1>标题</h1>
</body>
</html>

启动 jwebserver.

➜  bin ./jwebserver
Binding to loopback by default. For all interfaces use "-b 0.0.0.0" or "-b ::".
Serving /Users/darcy/develop/jdk-18.jdk/Contents/Home/bin and subdirectories on 127.0.0.1 port 8000
URL http://127.0.0.1:8000/

浏览器访问:

浏览器访问测试

有请求时会在控制台输出请求信息:

127.0.0.1 - - [26/3月/2022:16:53:30 +0800] "GET /favicon.ico HTTP/1.1" 404 -
127.0.0.1 - - [26/3月/2022:16:55:13 +0800] "GET / HTTP/1.1" 200 -

通过 help 参数可以查看 jwebserver 支持的参数。

➜  bin ./jwebserver --help
Usage: jwebserver [-b bind address] [-p port] [-d directory][-o none|info|verbose] [-h to show options][-version to show version information]
Options:
-b, --bind-address    - 绑定地址. Default: 127.0.0.1 (loopback).For all interfaces use "-b 0.0.0.0" or "-b ::".
-d, --directory       - 指定目录. Default: current directory.
-o, --output          - Output format. none|info|verbose. Default: info.
-p, --port            - 绑定端口. Default: 8000.
-h, -?, --help        - Prints this help message and exits.
-version, --version   - Prints version information and exits.
To stop the server, press Ctrl + C.

JEP 413:Javadoc 中支持代码片段

在 Java 18 之前,已经支持在 Javadoc 中引入代码片段,这样可以在某些场景下更好的展示描述信息,但是之前的支持功能有限,比如我想高亮代码片段中的某一段代码是无能为力的。现在 Java 18 优化了这个问题,增加了 @snippet 来引入更高级的代码片段。

在 Java 18 之前,使用 <pre>{@code ...}</pre> 来引入代码片段。

/*** 时间工具类* Java 18 之前引入代码片段:* <pre>{@code*     public static String timeStamp() {*        long time = System.currentTimeMillis();*         return String.valueOf(time / 1000);*     }* }</pre>**/

生成 Javadoc 之后,效果如下:

Javadoc 代码片段

高亮代码片段

从 Java 18 开始,可以使用 @snippet 来生成注释,且可以高亮某个代码片段。

/*** 在 Java 18 之后可以使用新的方式* 下面的代码演示如何使用 {@code Optional.isPresent}:* {@snippet :* if (v.isPresent()) {*     System.out.println("v: " + v.get());* }* }** 高亮显示 println** {@snippet :* class HelloWorld {*     public static void main(String... args) {*         System.out.println("Hello World!");      // @highlight substring="println"*     }* }* }**/

效果如下,更直观,效果更好。

正则高亮代码片段

甚至可以使用正则来高亮某一段中的某些关键词:

/** * 正则高亮:* {@snippet :*   public static void main(String... args) {*       for (var arg : args) {                 // @highlight region regex = "\barg\b"*           if (!arg.isBlank()) {*               System.out.println(arg);*           }*       }                                      // @end*   }*   }*/

生成的 Javadoc 效果如下:

替换代码片段

可以使用正则表达式来替换某一段代码。

/** * 正则替换:* {@snippet :* class HelloWorld {*     public static void main(String... args) {*         System.out.println("Hello World!");  // @replace regex='".*"' replacement="..."*     }* }* }*/

这段注释会生成如下 Javadoc 效果。

class HelloWorld {public static void main(String... args) {System.out.println(...);}
}

附:Javadoc 生成方式

# 使用 javadoc 命令生成 Javadoc 文档
➜  bin ./javadoc -public -sourcepath ./src -subpackages com -encoding utf-8 -charset utf-8 -d ./javadocout
# 使用 Java 18 的 jwebserver 把生成的 Javadoc 发布测试
➜  bin ./jwebserver -d /Users/darcy/develop/javadocout

访问测试:

JEP 416:使用方法句柄重新实现反射核心功能

Java 18 改进了 java.lang.reflect.MethodConstructor 的实现逻辑,使之性能更好,速度更快。这项改动不会改动相关 API ,这意味着开发中不需要改动反射相关代码,就可以体验到性能更好反射。

OpenJDK 官方给出了新老实现的反射性能基准测试结果。

Java 18 之前:

Benchmark                                     Mode  Cnt   Score  Error  Units
ReflectionSpeedBenchmark.constructorConst     avgt   10  68.049 ± 0.872  ns/op
ReflectionSpeedBenchmark.constructorPoly      avgt   10  94.132 ± 1.805  ns/op
ReflectionSpeedBenchmark.constructorVar       avgt   10  64.543 ± 0.799  ns/op
ReflectionSpeedBenchmark.instanceFieldConst   avgt   10  35.361 ± 0.492  ns/op
ReflectionSpeedBenchmark.instanceFieldPoly    avgt   10  67.089 ± 3.288  ns/op
ReflectionSpeedBenchmark.instanceFieldVar     avgt   10  35.745 ± 0.554  ns/op
ReflectionSpeedBenchmark.instanceMethodConst  avgt   10  77.925 ± 2.026  ns/op
ReflectionSpeedBenchmark.instanceMethodPoly   avgt   10  96.094 ± 2.269  ns/op
ReflectionSpeedBenchmark.instanceMethodVar    avgt   10  80.002 ± 4.267  ns/op
ReflectionSpeedBenchmark.staticFieldConst     avgt   10  33.442 ± 2.659  ns/op
ReflectionSpeedBenchmark.staticFieldPoly      avgt   10  51.918 ± 1.522  ns/op
ReflectionSpeedBenchmark.staticFieldVar       avgt   10  33.967 ± 0.451  ns/op
ReflectionSpeedBenchmark.staticMethodConst    avgt   10  75.380 ± 1.660  ns/op
ReflectionSpeedBenchmark.staticMethodPoly     avgt   10  93.553 ± 1.037  ns/op
ReflectionSpeedBenchmark.staticMethodVar      avgt   10  76.728 ± 1.614  ns/op

Java 18 的新实现:

Benchmark                                     Mode  Cnt    Score   Error  Units
ReflectionSpeedBenchmark.constructorConst     avgt   10   32.392 ± 0.473  ns/op
ReflectionSpeedBenchmark.constructorPoly      avgt   10  113.947 ± 1.205  ns/op
ReflectionSpeedBenchmark.constructorVar       avgt   10   76.885 ± 1.128  ns/op
ReflectionSpeedBenchmark.instanceFieldConst   avgt   10   18.569 ± 0.161  ns/op
ReflectionSpeedBenchmark.instanceFieldPoly    avgt   10   98.671 ± 2.015  ns/op
ReflectionSpeedBenchmark.instanceFieldVar     avgt   10   54.193 ± 3.510  ns/op
ReflectionSpeedBenchmark.instanceMethodConst  avgt   10   33.421 ± 0.406  ns/op
ReflectionSpeedBenchmark.instanceMethodPoly   avgt   10  109.129 ± 1.959  ns/op
ReflectionSpeedBenchmark.instanceMethodVar    avgt   10   90.420 ± 2.187  ns/op
ReflectionSpeedBenchmark.staticFieldConst     avgt   10   19.080 ± 0.179  ns/op
ReflectionSpeedBenchmark.staticFieldPoly      avgt   10   92.130 ± 2.729  ns/op
ReflectionSpeedBenchmark.staticFieldVar       avgt   10   53.899 ± 1.051  ns/op
ReflectionSpeedBenchmark.staticMethodConst    avgt   10   35.907 ± 0.456  ns/op
ReflectionSpeedBenchmark.staticMethodPoly     avgt   10  102.895 ± 1.604  ns/op
ReflectionSpeedBenchmark.staticMethodVar      avgt   10   82.123 ± 0.629  ns/op

可以看到在某些场景下性能稍微好些。

JEP 417:Vector API(三次孵化)

在 Java 16 中引入一个新的 API 来进行向量计算,它可以在运行时可靠的编译为支持的 CPU 架构,从而实现更优的计算能力。

在 Java 17 中改进了 Vector API 性能,增强了例如对字符的操作、字节向量与布尔数组之间的相互转换等功能。

现在在 JDK 18 中将继续优化其性能。

JEP 418:互联网地址解析 SPI

对于互联网地址解析 SPI,为主机地址和域名地址解析定义一个 SPI,以便 java.net.InetAddress 可以使用平台内置解析器以外的解析器。

InetAddress inetAddress = InetAddress.getByName("www.wdbyte.com");
System.out.println(inetAddress.getHostAddress());
// 输出
// 106.14.229.49

JEP 419:Foreign Function & Memory API (第二次孵化)

新的 API 允许 Java 开发者与 JVM 之外的代码和数据进行交互,通过调用外部函数,可以在不使用 JNI 的情况下调用本地库。

这是一个孵化功能;需要添加 --add-modules jdk.incubator.foreign 来编译和运行 Java 代码,Java 18 改进了相关 API ,使之更加简单易用。

历史

  • Java 14 JEP 370 (opens new window)[10] 引入了外部内存访问 API(孵化器)。

  • Java 15 JEP 383 (opens new window)[11] 引入了外部内存访问 API(第二孵化器)。

  • Java 16 JEP 389 (opens new window)[12] 引入了外部链接器 API(孵化器)。

  • Java 16 JEP 393 (opens new window)[13] 引入了外部内存访问 API(第三孵化器)。

  • Java 17 JEP 412 (opens new window)[14] 引入了外部函数和内存 API(孵化器)。

JEP 420:switch 表达式

从 Java 17 开始,对于 Switch 的改进就已经在进行了,Java 17 的 JEP 406 已经对 Switch 表达式进行了增强,使之可以减少代码量。

下面是几个例子:

// JDK 17 以前
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;
}

而在 Java 17 之后,可以通过下面的写法进行改进:

// JDK 17 之后
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();};
}

switch 可以和 null 进行结合判断:

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");}
}

case 时可以加入复杂表达式:

static void testTriangle(Shape s) {switch (s) {case Triangle t && (t.calculateArea() > 100) ->System.out.println("Large triangle");default ->System.out.println("A shape, possibly a small triangle");}
}

case 时可以进行类型判断:

sealed interface S permits A, B, C {}
final class A implements S {}
final class B implements S {}
record C(int i) implements S {}  // Implicitly finalstatic int testSealedExhaustive(S s) {return switch (s) {case A a -> 1;case B b -> 2;case C c -> 3;};
}

JEP 421:弃用删除相关

在未来将删除 Finalization,目前 Finalization 仍默认保持启用状态,但是已经可以手动禁用;在未来的版本中,将会默认禁用;在以后的版本中,它将被删除。需要进行资源管理可以尝试 try-with-resources 或者 java.lang.ref.Cleaner

引用链接

[1] 默认为 UTF-8: https://openjdk.java.net/jeps/400

[2] 简单的网络服务器: https://openjdk.java.net/jeps/408

[3] Java API 文档中的代码片段: https://openjdk.java.net/jeps/413

[4] 使用方法句柄重新实现核心反射: https://openjdk.java.net/jeps/416

[5] Vector API(三次孵化): https://openjdk.java.net/jeps/417

[6] 互联网地址解析 SPI: https://openjdk.java.net/jeps/418

[7] Foreign Function & Memory API (二次孵化): https://openjdk.java.net/jeps/419

[8] switch 模式匹配(二次预览): https://openjdk.java.net/jeps/420

[9] 弃用完成删除: https://openjdk.java.net/jeps/421

[10] JEP 370 (opens new window): https://openjdk.java.net/jeps/370

[11] JEP 383 (opens new window): https://openjdk.java.net/jeps/383

[12] JEP 389 (opens new window): https://openjdk.java.net/jeps/389

[13] JEP 393 (opens new window): https://openjdk.java.net/jeps/393

[14] JEP 412 (opens new window): https://openjdk.java.net/jeps/412


推荐阅读

  • 从输入 SQL 到返回数据,到底发生了什么?

  • 从俄乌战争看数字化的价值

  • 不要再用 where 1=1 了!有更好的写法!

  • 要不要赶个时髦,去建设一个「中台」?

  • 如何找到人生目标,有什么书可以推荐?

  • 性能优化的 6 个方向,看完瞬间变强了!

  • MySQL 锁机制存在的价值是什么?

  • 突发数据库锁表,如何快速解决?

  • 全网显示 IP 归属地,是怎么实现的?

  • MySQL 这 6 个文件,90% 的人都没认全!

  • 最新资讯!ONES 宣布收购「思否」技术社区!

Java 18 最新的九大新特性!相关推荐

  1. Visual Studio 11 九大新特性:图文详解【转】

    转自: [IT168 技术]导读:之前Visual Studio 11开发者预览版发布的消息受到了众多技术人员的关注和讨论.日前Visual Studio 11最新的Beta版本在巴塞罗那正式推出.我 ...

  2. Java9发布回顾Java 8的十大新特性

    java9已经在北京时间9月22日正式发布,开发者可以在oracle jdk官网上下载到最新的jdk9. 今天,我们先来一起复习一下2014年发布的Java 8的十大新特性.先来喝杯java~~~ 按 ...

  3. [转载] Java9发布回顾Java 8的十大新特性

    参考链接: Java中的DoubleStream mapToObj() java9已经在北京时间9月22日正式发布,开发者可以在oracle jdk官网上下载到最新的jdk9. 今天,我们先来一起复习 ...

  4. 【小家java】java9新特性(简述十大新特性) 褒贬不一

    相关阅读 [小家java]java5新特性(简述十大新特性) 重要一跃 [小家java]java6新特性(简述十大新特性) 鸡肋升级 [小家java]java7新特性(简述八大新特性) 不温不火 [小 ...

  5. Java基础学习总结(33)——Java8 十大新特性详解

    Java8 十大新特性详解 本教程将Java8的新特新逐一列出,并将使用简单的代码示例来指导你如何使用默认接口方法,lambda表达式,方法引用以及多重Annotation,之后你将会学到最新的API ...

  6. 【小家java】java10新特性(简述十大新特性) 小步迭代

    相关阅读 [小家java]java5新特性(简述十大新特性) 重要一跃 [小家java]java6新特性(简述十大新特性) 鸡肋升级 [小家java]java7新特性(简述八大新特性) 不温不火 [小 ...

  7. Java8的十大新特性

    Java9预计将于今年9月份发布,这是否会是一次里程碑式的版本,我们拭目以待.今天,我们先来复习一下2014年发布的Java 8的十大新特性. Java 8可谓是自Java 5以来最具革命性的版本了, ...

  8. Java 5~11各个版本新特性史上最全总结

    Java 5 Java5开发代号为Tiger(老虎),于2004-09-30发行 特性列表 泛型 枚举 自动装箱拆箱 可变参数 注解 foreach循环(增强for.for/in) 静态导入 格式化( ...

  9. C# 9.0 终于来了, Top-level programs 和 Partial Methods 两大新特性探究

    一:背景 1. 讲故事 .NET 5 终于在 6月25日 发布了第六个预览版,随之而来的是更多的新特性加入到了 C# 9 Preview 中,这个系列也可以继续往下写了,废话不多说,今天来看一下 To ...

最新文章

  1. 创建mysql数据库,在新数据库中创建表,再尝试删除表
  2. Linux学习记录--开机挂载错误
  3. VS2005下 auxDIBImageLoad() 这个函数真囧
  4. js实现向上滚动效果
  5. STL浅析——序列式容器vector的数据结构
  6. vnc报错 font catalog is not properly configured
  7. dxf转g代码_恶意代码分析系列几种常用技术(2)
  8. 一加7 Pro详细配置规格曝光:售价妥妥破5000
  9. Linux笔记(shell特殊符号,sort排序,wc统计,uniq去重,tee,tr,split)
  10. Parallels Desktop 17 “操作失败 执行该操作失败”的解决方法
  11. git覆盖覆盖推送_强制“git Push”覆盖远程文件
  12. Flask-APScheduler使用教程
  13. Tableau数据连接与加载(数据提取)
  14. bat脚本转成exe执行程序
  15. 围棋智能机器人阿法狗,阿尔法狗机器人围棋
  16. 我在使用Next.js, Antd, @zeit/next-css时遇到的一些问题
  17. soap python_Zeep: Python SOAP 客户端
  18. 线性代数的本质(Essense Of Linear Algebra)[2]
  19. C++语言基础——C++一本通:第四章 循环结构的程序设计:第一节 for语句:1082:求小数的某一位
  20. python 包络线_Matlab 如何绘制复杂曲线的包络线

热门文章

  1. Redis( 缓存篇 ==> 互斥锁解决缓存击穿
  2. 百世集团2016校园招聘开发工程师笔试试卷
  3. leetcode17题 电话号码的字母组合
  4. 智能车的“耳朵”电磁检测传感器
  5. 上海市建平中学2021年高考成绩查询,2021年上海市高中排名一览表
  6. 华为ENSP实验之静态路由配置
  7. vs code新版本,解决感叹号无法生成HTML骨架的方法
  8. 常微分方程数值解matlab欧拉,MATLAB实验报告_常微分方程数值解
  9. Spring Boot 错题本
  10. python-报错集合