强封装核心在于通过module-info.java显式exports导出包,未声明则完全不可见;opens仅按需开放反射,requires transitive控制依赖传递,全程由JVM强制执行。

通过 module-info.java 实现强封装,核心在于 **显式声明哪些包对外可访问(exports),未声明的包默认不可见**;同时配合 opens、uses、provides 等指令精细控制反射、服务发现等特殊场景的访问边界。
exports:严格限定公开API包
模块默认不导出任何包,这是强封装的基础。只有用 exports 明确声明的包,其他模块才能访问其中的 public 类型和成员:
-
exports com.example.api;—— 允许所有模块访问该包 -
exports com.example.api to com.example.client;—— 仅允许指定模块访问(qualified export),实现更细粒度隔离 - 未被
exports的包(如com.example.internal)即使全是 public 类,在编译期和运行期均无法被其他模块解析或链接
opens:按需开放反射访问(非默认)
反射访问(如 Class.getDeclaredMethod()、Field.setAccessible(true))在模块系统中受额外限制。即使包已 exports,其内部成员仍不能被反射访问,除非显式 opens:
-
opens com.example.config;—— 允许所有模块对该包进行深层反射操作 -
opens com.example.config to com.example.bootstrap;—— 仅授权特定模块反射访问,避免框架滥用 -
opens不等于exports:前者只解禁反射,不提供编译期可见性
requires transitive 与 implied readability:控制依赖传递性
强封装要求明确依赖边界,避免隐式可访问:
-
requires java.sql;—— 当前模块依赖 SQL API,但不向下游暴露它 -
requires transitive java.sql;—— 下游模块若依赖本模块,将自动获得对java.sql的 readability(即“隐式 requires”),适用于 API 组合场景(如 ORM 模块导出依赖的 JDBC 类型) - 慎用
transitive:它会扩大封装边界,违背最小暴露原则;优先让调用方显式声明所需依赖
禁止跨模块访问内部类与包私有元素
模块系统强化了 Java 原有访问控制语义:
- 同一模块内,
package-private(默认访问级别)成员仍可被本模块所有包访问 - 跨模块时,即使目标类是 public,其 package-private 字段/方法也无法被访问(编译失败)
- 嵌套类(如
public static class Helper)若所在顶层类未被导出,或其自身包未被 exports,外部模块根本无法加载该类型
模块化强封装不是靠代码注释或约定,而是由编译器和 JVM 在构建与运行阶段强制执行。只要坚持“不 exports 就不可见”“不 opens 就不可反射”,就能真正切断非预期的耦合路径。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











