Module-info.java文件
文章目录
- 一、module-info.java 的所有关键字
- 1. 模块定义关键字
- 2. 依赖声明关键字
- 3. 包导出关键字
- 4. 服务相关关键字
- 5. 反射访问关键字
- 二、关键字表
- 三、关键字的搭配与实际场景
- 1. 依赖与导出
- 2. 服务提供与消费
- 3. 反射控制
- 四、注意事项
- 五、完整示例
- 六、总结
一、module-info.java 的所有关键字
在 Java 模块化系统(JPMS)中(jdk9后的新特性),module-info.java 文件使用以下关键字来定义模块的结构、依赖和服务。以下是按照功能分组的列表:
1. 模块定义关键字
-
module
-
作用:定义模块的名称,标志模块声明的开始。
-
语法:module <模块名> { … }
-
示例:
module com.example.myapp { // 模块内容 }
-
说明:模块名通常遵循反向域名规则(如 com.example.myapp),是模块的唯一标识。
-
2. 依赖声明关键字
-
requires
-
作用:声明当前模块依赖的其他模块。
-
语法:requires [修饰符] <模块名>;
-
修饰符(可选):
- transitive:依赖是传递的,依赖当前模块的模块也会自动依赖它。
- static:依赖是可选的,编译时需要,运行时可以没有。
-
示例:
module com.example.myapp { requires java.base; // 默认依赖基础模块 requires transitive java.sql; // 传递依赖 requires static java.logging; // 可选依赖 }
-
说明:java.base 是所有模块的默认依赖,无需显式声明。
-
3. 包导出关键字
-
exports
-
作用:声明当前模块的某个包可以被其他模块访问。
-
语法:
- exports <包名>;(开放给所有模块)
- exports <包名> to <模块名列表>;(限制给特定模块)
-
示例:
module com.example.myapp { exports com.example.myapp.api; // 开放给所有模块 exports com.example.myapp.util to com.example.client; // 仅限特定模块 }
-
说明:
- 包必须存在于模块中,否则编译报错。
- 未导出的包对外部模块不可见。
-
4. 服务相关关键字
-
provides
-
作用:声明当前模块为某个服务接口提供具体实现。
-
语法:provides <接口全限定名> with <实现类全限定名>;
-
示例:
module com.example.myapp { provides com.example.service.MyService with com.example.myapp.MyServiceImpl; }
-
说明:
- 与 with 配合使用,指定实现类。
- 表示模块是服务提供者,供其他模块通过 ServiceLoader 加载。
-
-
with
-
作用:配合 provides 使用,指定服务接口的具体实现类。
-
语法:出现在 provides 语句中,with 后接实现类的全限定名。
-
示例:
provides javax.tools.JavaCompiler with com.example.myapp.MyCompiler;
-
说明:
- 实现类必须是接口的合法实现(实现接口或继承抽象类)。
- 可以为一个接口提供多个实现,用多个 with 分隔。
-
-
uses
-
作用:声明当前模块使用某个服务接口,期待其他模块提供实现。
-
语法:uses <接口全限定名>;
-
示例:
module com.example.myapp { uses com.example.service.MyService; }
-
说明:
- 表示模块是服务消费者,通过 ServiceLoader 加载接口实现。
- 常与 provides 配合使用,形成服务提供-消费模式。
-
5. 反射访问关键字
-
opens
-
作用:声明某个包对反射开放,允许其他模块在运行时通过反射访问。
-
语法:
- opens <包名>;(开放给所有模块)
- opens <包名> to <模块名列表>;(限制给特定模块)
-
示例:
module com.example.myapp { opens com.example.myapp.data; // 开放给所有模块反射 opens com.example.myapp.config to com.example.client; // 仅限特定模块 }
-
说明:
- 不影响编译时访问,只开放运行时反射(如 setAccessible)。
- 适用于需要反射的场景(如序列化框架)。
-
-
open
-
作用:声明整个模块对反射开放,所有包都可以被反射访问。
-
语法:open module <模块名> { … }
-
示例:
open module com.example.myapp { exports com.example.myapp.api; }
-
说明:
- 是模块级别的反射开放,比 opens 更彻底。
- 常用于兼容非模块化代码或调试。
-
二、关键字表
关键字 | 功能 | 示例 |
---|---|---|
module | 定义模块 | module com.example.myapp {} |
requires | 声明依赖模块 | requires java.sql; |
exports | 导出包给其他模块 | exports com.example.myapp.api; |
provides | 提供服务接口实现 | provides X with Y; |
with | 指定服务实现的类 | with com.example.myapp.MyServiceImpl; |
uses | 声明使用服务接口 | uses javax.tools.JavaCompiler; |
opens | 开放包给反射访问 | opens com.example.myapp.data; |
open | 定义开放模块(全部包可反射) | open module com.example.myapp {} |
三、关键字的搭配与实际场景
1. 依赖与导出
-
requires + exports:最常见组合,用于模块间的依赖和接口共享。
module com.example.client { requires com.example.myapp; // 使用 com.example.myapp 导出的包 } module com.example.myapp { exports com.example.myapp.api; }
2. 服务提供与消费
-
provides + with + uses:实现插件化机制。
module com.example.provider { provides com.example.service.MyService with com.example.provider.MyServiceImpl; } module com.example.consumer { uses com.example.service.MyService; }
-
消费端代码:
ServiceLoader<MyService> loader = ServiceLoader.load(MyService.class); for (MyService service : loader) { service.doSomething(); }
-
3. 反射控制
-
opens + exports:既允许编译时访问,又开放运行时反射。
module com.example.myapp { exports com.example.myapp.api; opens com.example.myapp.data; }
四、注意事项
- 包存在性
- exports 和 opens 声明的包必须在模块中存在,否则编译报错。
- 空包(无类或资源)可能导致错误。
- 服务机制
- provides 的实现类必须是 uses 接口的合法实现。
- 一个接口可以有多个 with 实现。
- 修饰符限制
- requires 的 transitive 和 static 不能同时使用。
- exports 和 opens 的 to 后接模块名列表,用逗号分隔。
五、完整示例
以下是一个综合所有关键字的 module-info.java:
open module com.example.myapp {
requires transitive java.sql; // 传递依赖
requires static java.logging; // 可选依赖
exports com.example.myapp.api; // 导出 API 包
exports com.example.myapp.util to com.example.client; // 限制导出
provides com.example.service.MyService with com.example.myapp.MyServiceImpl; // 服务实现
uses com.example.service.MyService; // 使用服务接口
opens com.example.myapp.data; // 开放反射
opens com.example.myapp.config to com.example.client; // 限制开放
}
六、总结
module-info.java 的关键字虽然数量有限,但功能强大,涵盖了模块定义、依赖管理、包导出、服务提供和反射控制等核心特性。