JDK 9 带来了很多显著的新特性,较早期的版本有了非常多的提升和优化。以下将以清晰的对比方式讲解 JDK 9 相比旧版本的优势,并通过实际示例展示如何利用新特性。
1. 模块化系统(Project Jigsaw)
JDK 8 及之前:
所有的 Java 类都在一个巨大的类库中,JDK 无法轻松拆分为不同部分。大型项目会有类冲突、依赖混乱等问题,模块间的依赖关系难以管理。
JDK 9:
JDK 9 引入了 模块化系统,将 JDK 拆分为多个模块,使得开发者可以构建更小的、仅包含必要模块的应用。模块系统允许显式声明模块的依赖关系,避免模块依赖的混乱。
优势:
- 减少类加载冲突
- 构建更小的自定义 JRE
- 提高代码维护性和安全性
示例:
在 JDK 9 中,开发者可以使用 module-info.java
文件声明模块:
module com.example.module {
exports com.example.module; // 模块导出包
requires java.sql; // 声明依赖
}
通过 jlink
构建定制化 JRE:
jlink --module-path $JAVA_HOME/jmods --add-modules java.base,java.sql --output custom-runtime
2. HTTP/2 Client API
JDK 8 及之前:
之前使用 HttpURLConnection
或第三方库(如 Apache HttpClient)来发送 HTTP 请求,代码通常比较冗长,且不支持 HTTP/2。
// HttpURLConnection 示例
URL url = new URL("http://example.com");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuilder content = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
content.append(inputLine);
}
in.close();
con.disconnect();
System.out.println(content.toString());
JDK 9:
引入了 新的 HTTP/2 Client API,支持异步处理和 WebSocket,简化了 HTTP 请求的编写,特别是对于 HTTP/2 的支持。相比 HTTP/1.1,HTTP/2 支持多路复用,头部压缩,更有效的连接管理。
// HTTP/2 Client 示例
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("http://example.com"))
.build();
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(System.out::println)
.join();
优势:
- 支持 HTTP/2 和 WebSocket
- 异步操作更方便
- 不再需要依赖第三方库
3. JShell(交互式 REPL)
JDK 8 及之前:
在 JDK 8 及之前的版本中,Java 开发者无法在命令行中进行简单的代码实验。需要编写完整的类、方法,编译和运行后才能看到效果。
JDK 9:
引入了 JShell,这是 Java 的交互式 REPL(Read-Eval-Print Loop)工具,允许开发者快速实验代码片段而不需要编写完整的类和方法。
优势:
- 适合初学者学习和实验
- 提高开发和测试效率
示例:
启动 JShell 并测试:
$ jshell
jshell> int a = 5;
jshell> System.out.println(a * 2); // 输出 10
4. 增强的集合工厂方法
JDK 8 及之前:
创建不可变集合需要手动实现,或者使用 Collections.unmodifiableList()
,代码较为冗长且不够直观。
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
List<String> unmodifiableList = Collections.unmodifiableList(list);
JDK 9:
引入了 新的集合工厂方法,例如 List.of()
、Set.of()
和 Map.of()
,可以直接创建不可变集合。
List<String> list = List.of("a", "b", "c");
Set<String> set = Set.of("x", "y", "z");
Map<String, Integer> map = Map.of("key1", 1, "key2", 2);
优势:
- 更简洁、易读
- 代码少且更易维护
5. 私有接口方法
JDK 8 及之前:
接口中只能定义抽象方法或 default
和 static
方法,若有公共逻辑,只能定义为默认方法,无法进一步封装。
JDK 9:
JDK 9 允许在接口中定义私有方法,使接口逻辑更加封装,减少代码重复。
interface MyInterface {
default void showMessage() {
System.out.println(getMessage());
}
private String getMessage() {
return "Hello, Private Method!";
}
}
优势:
- 代码复用,减少冗余逻辑
- 提高接口的内聚性
6. 多版本 JAR 文件
JDK 8 及之前:
JAR 文件只能适应单个版本的 JVM,若需要支持多个 JDK 版本,开发者只能通过不同的 JAR 文件或条件编译来解决。
JDK 9:
支持 多版本 JAR 文件,允许在同一个 JAR 文件中包含多个版本的类文件,以便不同 JDK 版本能够加载适合自己的类。
META-INF/versions/9/com/example/MyClass.class
优势:
- 在同一 JAR 中支持多个 Java 版本,增强兼容性
7. G1 垃圾收集器默认启用
JDK 8 及之前:
JDK 8 默认使用 Parallel GC,适合高吞吐量的应用,但在暂停时间控制上表现较差。若需低暂停的 GC,开发者需手动启用 G1 GC。
JDK 9:
JDK 9 将 G1 GC 设置为默认垃圾收集器,G1 旨在减少最大暂停时间,适合大多数服务器应用场景。
优势:
- 更好地控制暂停时间,适合低延迟应用
8. jlink - 自定义 Java 运行时
JDK 8 及之前:
JDK 8 不支持创建自定义的运行时环境,开发者只能通过完整的 JDK 或 JRE 部署应用,内存占用较大,且包含许多不必要的模块。
JDK 9:
通过 jlink 工具,开发者可以构建仅包含必要模块的自定义运行时环境,减小部署包大小,特别适合嵌入式设备或云端微服务。
jlink --module-path $JAVA_HOME/jmods --add-modules java.base,java.logging --output custom-jre
优势:
- 减少应用占用的内存和磁盘空间
- 适用于资源受限的环境
总结
JDK 9 的新特性在模块化设计、集合处理、HTTP 客户端、垃圾收集等方面提供了更简洁、更高效的解决方案。相比 JDK 8,它更适合现代软件开发场景,如微服务、云原生应用和异步编程,开发者可以更轻松地编写高效、灵活的代码。