module-info.java 是 java 9+ 模块系统的唯一配置入口,所有指令必须写在 module { ... } 块内;模块名须为合法标识符且全局唯一,采用反向域名格式;requires 声明依赖,transitive 控制传递性;exports 控制包可见性,opens 支持反射访问;uses/provides 显式声明服务机制。

module-info.java 是 Java 9+ 模块系统的唯一配置入口,所有指令必须写在 module { ... } 块内,语法严格、顺序无关,但语义必须清晰准确。写错位置、漏掉关键字或误用修饰符都会导致编译失败或运行时访问异常。
模块声明与命名规则
模块名必须是合法的 Java 标识符,通常采用小写字母加点号的反向域名格式(如 com.example.auth),不能含大写字母、下划线或连字符。模块名一旦确定,就成为该模块在整个系统中的唯一身份标识。
- 模块声明以
module关键字开头,后跟模块名和大括号,例如:module com.example.auth { ... } - 模块名不等于包名,但建议与主包保持逻辑一致;一个模块可包含多个包,也可只含资源文件
- 模块名不能重复,否则在模块路径中会引发冲突
依赖声明:requires 与 transitive
requires 是最常用的指令,用于显式声明当前模块对其他模块的编译与运行时依赖。它不自动传递——除非加上 transitive。
- 基础写法:
requires java.logging;表示本模块能访问java.logging中导出的 public 类 - 若 A 模块 requires B,而 B 又 requires java.xml,则 A 默认无法使用
java.xml的类;需在 B 中写requires transitive java.xml;,A 才能间接访问 - 系统模块如
java.base虽被隐式依赖,但显式写出更清晰,也便于工具分析
包可见性控制:exports 与 opens
exports 决定哪些包能被其他模块的代码直接 import 和调用;opens 则专为反射场景设计,仅允许指定模块在运行时通过 ClassLoader 或反射 API 访问包内成员。
- 导出整个包:
exports com.example.service; - 限制导出范围(推荐):
exports com.example.api to com.example.client;表示只允许com.example.client模块访问该包 - 开放包供反射:
opens com.example.config;或限定模块:opens com.example.model to spring.core; - 未
exports的包对外完全不可见,即使类是 public 也会编译报错
服务机制:uses 与 provides
服务加载机制(SPI)在模块化下需显式声明。服务接口由 uses 引入,具体实现由 provides ... with 提供。
- 声明使用某服务:
uses com.example.spi.Encoder; - 提供服务实现:
provides com.example.spi.Encoder with com.example.impl.JsonEncoder; - 一个模块可提供多个实现,也可由不同模块分别提供;运行时 ServiceLoader 会按模块路径顺序查找
- 服务接口本身必须被导出,否则其他模块无法声明
uses
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











