Java 9 新特性(建议收藏)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观
前言
Java 9 是 Java 生态系统的一次重要升级,它不仅引入了模块化系统这一革命性功能,还通过一系列语法优化和 API 增强,让开发者能够更高效地构建和维护复杂项目。对于编程初学者而言,这些新特性降低了学习曲线;对于中级开发者,它们则提供了提升代码质量和可维护性的新工具。本文将逐一解析 Java 9 的核心新特性,并通过具体案例帮助读者理解其应用场景。
模块化系统(JPMS):Java 的“城市规划师”
Java 9 最引人注目的新特性是 Java Platform Module System (JPMS),它首次将模块化引入 Java 核心。模块化可以类比为“城市规划”:通过将代码划分为独立的模块(Module),开发者能明确依赖关系,避免“依赖地狱”问题。
模块化的核心概念
- 模块声明(Module Declaration):每个模块通过
module-info.java
文件定义,声明导出的包和依赖的其他模块。 - 包访问控制:默认情况下,包仅对模块内部可见,需显式导出(
exports
)才能被其他模块使用。 - 服务提供者机制:通过
uses
和provides
关键字,模块可以声明对服务接口的支持。
示例代码:定义一个简单模块
// module-info.java
module my.module {
requires java.base; // 引用基础模块
exports my.module.utils; // 导出 utils 包
uses com.example.ServiceInterface; // 声明使用某个服务接口
}
模块化的优势
- 减少启动时间:通过类路径隔离,JVM 可以仅加载必要模块。
- 提高安全性:限制包的可见性,减少未授权访问风险。
- 清晰的依赖管理:模块间的依赖关系显式声明,避免隐式依赖。
新的集合工厂方法:让代码更简洁
Java 9 为 List
、Set
和 Map
接口引入了 静态工厂方法,简化了集合的创建和初始化。这些方法类似于 Arrays.asList()
,但更灵活且返回不可变集合。
示例:创建不可变列表
List<String> fruits = List.of("Apple", "Banana", "Orange");
// fruits.add("Grape"); // 抛出 UnsupportedOperationException
集合工厂方法的特点
- 类型推断:编译器自动推断元素类型,无需显式声明泛型。
- 不可变性:返回的集合是只读的,避免意外修改。
- 空安全:若传入
null
元素,会抛出NullPointerException
。
对比:Java 8 与 Java 9 的代码差异
// Java 8
List<String> oldList = new ArrayList<>();
oldList.add("Java");
oldList.add("Python");
// Java 9
List<String> newList = List.of("Java", "Python");
私有接口方法:接口中的“共享工具箱”
在 Java 9 之前,接口只能定义默认方法和静态方法。Java 9 引入了 私有接口方法,允许在接口中定义私有辅助方法,供默认方法或静态方法调用。
为什么需要私有接口方法?
- 代码复用:将重复逻辑封装在私有方法中,避免多个默认方法的冗余代码。
- 封装性:私有方法对外不可见,确保接口的简洁性。
示例:计算器接口的私有方法
interface Calculator {
// 默认方法
default int add(int a, int b) {
return calculate(a, b, (x, y) -> x + y);
}
// 私有接口方法
private int calculate(int a, int b, BiFunction<Integer, Integer, Integer> op) {
return op.apply(a, b);
}
}
私有方法的限制
- 只能在接口内部调用,无法被实现类或外部访问。
- 不能声明为
static
或public
。
var 关键字:局部变量的“类型推断”
Java 9 引入了 var
关键字,允许开发者在局部变量声明时省略显式类型,由编译器根据赋值表达式推断类型。这提升了代码的简洁性,但需谨慎使用以避免可读性下降。
使用场景与注意事项
- 适用场景:变量初始化时类型明显,如循环变量、简单赋值。
- 避免场景:复杂表达式或可能变更类型的变量。
示例:var
的典型用法
var numbers = List.of(1, 2, 3); // 推断为 List<Integer>
var scanner = new Scanner(System.in); // 推断为 Scanner
与 C# var
的对比
Java 的 var
仅限局部变量,且要求初始化时有明确的赋值表达式,而 C# 的 var
可用于字段和更复杂的上下文。
Stream API 的增强:更精准的数据处理
Java 9 扩展了 Stream
接口的功能,新增了 dropWhile
、takeWhile
和 ofNullable
等方法,进一步简化流式数据处理。
新增方法详解
方法 | 功能描述 |
---|---|
takeWhile(Predicate) | 当条件满足时持续收集元素,条件不满足时终止。 |
dropWhile(Predicate) | 跳过满足条件的元素,直到条件不满足后收集剩余元素。 |
ofNullable(T) | 将可能为 null 的单个元素安全转换为 Stream。 |
示例:takeWhile
的实际应用
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6);
numbers.stream()
.takeWhile(n -> n < 4)
.forEach(System.out::print); // 输出 123
JShell:Java 的“即时编程环境”
Java 9 内置了 JShell,这是一个交互式 Java REPL(Read-Eval-Print Loop),允许开发者直接执行代码片段并查看结果,极大提升了学习和调试效率。
JShell 的核心功能
- 快速测试代码:无需编写完整类和方法,直接输入表达式即可。
- 自动补全和错误提示:提供实时语法检查和上下文建议。
- 会话管理:支持保存和恢复交互记录。
示例:在 JShell 中运行代码
jshell> int a = 10
a ==> 10
jshell> System.out.println("Hello, JShell!")
Hello, JShell!
新的 HTTP Client API:现代化的网络请求
Java 9 引入了 标准的 HTTP Client API(java.net.http
包),替代了旧版的 HttpURLConnection
,支持异步请求、WebSocket 和 HTTP/2 协议。
API 核心类
HttpClient
:发送请求的客户端。HttpRequest
:构建 HTTP 请求对象。HttpResponse
:接收响应结果。
示例:发送 GET 请求
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder(URI.create("https://api.example.com/data"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
其他改进:细节优化与性能提升
1. Process API 的增强
新增了 ProcessHandle
类,支持监控和管理操作系统进程,例如:
Process process = Runtime.getRuntime().exec("ping localhost");
ProcessHandle handle = ProcessHandle.of(process.pid());
handle.info().command().ifPresent(System.out::println);
2. 集合类的增强
Map.getOrDefault
方法简化了键不存在时的默认值获取。Collection.removeIf
支持通过 Predicate 条件批量删除元素。
3. Optional 的新方法
Stream
可以直接从 Optional
生成:
Optional<String> maybeValue = Optional.of("Hello");
maybeValue.stream().forEach(System.out::print); // 输出 Hello
结论
Java 9 的新特性从模块化、语法糖到 API 增强,全面提升了 Java 的开发体验和工程实践。对于初学者,模块化和 var
等特性降低了代码复杂度;对于中级开发者,JShell 和 HTTP Client 则提供了更高效的工具链。掌握这些新特性,不仅能提高编码效率,还能为后续 Java 版本的升级打下坚实基础。
在实践中,建议读者通过实际项目逐步应用这些特性,并关注 Oracle 官方文档和社区讨论,以持续优化开发流程。Java 9 的诞生,标志着 Java 正朝着更模块化、更现代化的方向稳步前进。