共计 6544 个字符,预计需要花费 17 分钟才能阅读完成。
你好啊,我是大阳,明天给大家介绍一下 Java9 的新个性,并提供一些代码示例。
Java 9 带来了许多新的加强性能,这些加强性能将在很大水平上影响你的编程格调和习惯。最大的变动是 Java 的模块化。这是继 Java 8 中的 Lambdas 之后的另一个重大变动。在本文中,我将列出 Java 9 版本的一部分更新内容。
本文次要内容:
- Java 模块化
- 接口公有办法
- HTTP/ 2 客户端
- JShell – REPL 工具
- 平台和 JVM 日志记录
- Process API 更新
- Collection(汇合)API 更新
- Stream(流)API 改良
- 多版本 Jar 文件
- @Deprecated 注解更改
- Java 文档更新
- 其余性能
1. Java 模块化
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;}
2. 接口公有办法
Java 8 容许在接口中编写默认办法,这是一个广受欢迎的性能。从 Java 9 开始,您能够在接口中蕴含公有办法。
这些公有办法将进步接口外部的代码可重用性。例如,如果两个默认办法须要共享代码,公有接口办法将容许它们这样做,但不会将该公有办法裸露给它的实现类。
在接口中应用公有办法有四个规定:
- 公有接口办法不能是形象的。
- 公有办法只能在接口外部应用。
- 公有静态方法能够在其余动态和非动态接口办法中应用。
- 公有非静态方法不能在公有静态方法中应用。
示例:
public interface CustomCalculator {default int addEvenNumbers(int... nums) {return add(n -> n % 2 == 0, nums);
}
default int addOddNumbers(int... nums) {return add(n -> n % 2 != 0, nums);
}
private int add(IntPredicate predicate, int... nums) {return IntStream.of(nums)
.filter(predicate)
.sum();}
}
3. HTTP/ 2 客户端
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/")).GET().build();
HttpResponse<String> httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandler.asString());
System.out.println(httpResponse.body());
下面的代码看起来更清晰易读。
httpClient.sendAsync()
API 还反对应用办法的异步 HTTP 申请。它返回 CompletableFuture
可用于确定申请是否已实现。它还能够在 HttpResponse
申请实现后拜访。如果你违心,甚至能够在申请实现之前勾销它。
示例:
if(httpResponse.isDone()) {System.out.println(httpResponse.get().statusCode());
System.out.println(httpResponse.get().body());
} else {httpResponse.cancel(true);
}
4. JShell – REPL 工具
JShell 是 JDK 9 发行版 [JEP 222]附带的新命令行交互式工具,用于评估用 Java 编写的申明、语句和表达式。JShell 容许咱们执行 Java 代码片段并立刻取得后果,而无需创立解决我的项目。
Jshell 很像咱们在 linux 操作系统中的命令窗口。不同之处在于 JShell 是特定于 Java 的。除了执行简略的代码片段之外,它还有许多其余性能,例如:
- 在独自的窗口中启动内置代码编辑器
- 在独自的窗口中启动你抉择的代码编辑器
- 在这些内部编辑器中产生保留操作时执行代码
- 从文件系统加载事后编写的类
5. 平台和 JVM 日志记录
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
.
6. Process API 更新
在 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"));
System.out.println(processInfo.startInstant().isPresent());
要获取新衍生过程的信息,请应用 process.toHandle()
办法获取 ProcessHandle
实例。其余所有如上。
String javaPrompt = ProcessUtils.getJavaCmd().getAbsolutePath();
ProcessBuilder processBuilder = new ProcessBuilder(javaPrompt, "-version");
Process process = processBuilder.inheritIO().start();
ProcessHandle processHandle = process.toHandle();
也用于 ProcessHandle.allProcesses()
获取零碎中所有可用过程的 ProcessHandle 流。
要获取所有子过程的列表(间接以及 n 级深度),请应用 children()
和descendants()
办法。
Stream<ProcessHandle> children = ProcessHandle.current().children();
Stream<ProcessHandle> descendants = ProcessHandle.current().descendants();
6. Collection(汇合)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", "Amit", "John");
Set<String> namesSet = Set.of("Lokesh", "Amit", "John");
Map<String, String> namesMap = Map.ofEntries(Map.entry("1", "Lokesh"),
Map.entry("2", "Amit"),
Map.entry("3", "Brian"));
}
}
7. Stream(流)API 改良
Java 9 引入了两种与 Streams 交互的新办法,即 takeWhile
/dropWhile
办法。此外,它还增加了两个重载办法,即 ofNullable
和iterate
办法。
新办法 takeWhile
。dropWhile
容许开发者基于谓词获取流的一部分
- 在有序流上,
takeWhile
返回从流中获取的与给定谓词匹配的元素的“最长前缀”,从流的结尾开始。dropWhile
返回与 不匹配的残余我的项目takeWhile
。 - 在无序流上,
takeWhile
返回与给定谓词(但不是全副)匹配的流元素的子集,从流的结尾开始。dropWhile
在删除与给定谓词匹配的元素子集后返回残余的流元素。
List<String> alphabets = List.of("a", "b", "c", "d", "e", "f", "g", "h", "i");
List<String> subset1 = alphabets
.stream()
.takeWhile(s -> !s.equals("d"))
.collect(Collectors.toList());
// 打印出:[a, b, c]
System.out.println(subset1);
List<String> alphabets = List.of("a", "b", "c", "d", "e", "f", "g", "h", "i");
List<String> subset2 = alphabets
.stream()
.dropWhile(s -> !s.equals("d"))
.collect(Collectors.toList());
// 打印出:[d, e, f, g, h, i]
System.out.println(subset2);
同样,在 Java 8 之前,流中不能有 null 值。它会导致 NullPointerException
. 从 Java 9 开始,Stream.ofNullable()
办法容许您创立一个单元素流,该流包装一个不为 null 的值,否则为空流。从技术上讲,Stream.ofNullable()
在流 API 的上下文中,与空条件查看十分类似。
8. 多版本 Jar 文件
此加强与如何将应用程序类打包到 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 彼此不兼容。此性能能够为解决这些状况提供很大帮忙。
9. @Deprecated 注解更改
从 Java 9 开始,@Deprecated 注解将具备两个属性,即 forRemoval
和since
.
- forRemoval – 批示带正文的元素是否会在将来版本中被删除。
- since – 它返回正文元素被弃用的版本。
强烈建议应用 @deprecated javadoc 标记在文档中解释弃用程序元素的起因。如果实用,文档还应倡议并链接到举荐的代替 API。替换 API 通常具备奥妙不同的语义,因而也应探讨此类问题。
10. Java 文档更新
Java 9 加强了 javadoc
生成 HTML5 标记的工具。它目前以 HTML 4.01 生成页面。
为了生成 HTML5 Javadoc,参数 -html5
须要放在命令行参数中。要在命令行上生成文档,你将运行:
javadoc [选项] [包名] [源文件] [@files]
应用 HTML5 能够带来更简略的 HTML5 构造的益处。它还实现了可拜访性的 WAI-ARIA 规范。这旨在使身材或视觉阻碍的人更容易应用屏幕阅读器等工具拜访 javadocs 页面。
JEP 225 提供了在 javadoc 中搜寻程序元素和标记的单词和短语的能力。
以下内容将被索引和搜寻:
- 模块的申明名称
- 套餐
- 类型和成员
- 办法参数类型的简略名称
这是在客户端实现的,带有一个新的search.js
Javascript 文件,以及生成 javadoc 时生成的索引。生成的 HTML5 API 页面上有一个搜寻框。
请留神,默认状况下会增加搜寻选项,但能够应用参数敞开:-noindex
。
11. 其余性能
Java 9 中还有其余性能,我在此处列出以供疾速参考。咱们将在接下来的帖子中探讨所有这些性能。
- 反应式流 API
- GC(垃圾收集器)改良
- 过滤传入的序列化数据
- 弃用 Applet API
- 批示字符串连贯
- 加强的办法句柄
- 紧凑的字符串
- Nashorn 解析器 API