商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > Java 9模块化系统(JPMS):控制对象变量跨包访问权限指南

Java 9模块化系统(JPMS):控制对象变量跨包访问权限指南

  发布于2026-07-06 阅读(0)

扫一扫,手机访问

今天聊聊 Ja va 9 模块化系统里一个特别容易让人懵圈的问题——它到底控制的是什么东西的访问权限?

先说一个核心判断:JPMS 从来不直接管什么“对象变量”能不能跨包访问。它管的是跨模块的访问权限,具体来说,是一个模块里的包、类、成员,能不能被另一个模块看到、用到。至于同一个模块里不同包之间怎么访问,不好意思,这事依然归传统的 publicprotected、包私有、private 这些老伙计管。模块系统只会在模块边界上站岗——当外部模块的代码试图访问你的内部时,它才会出手。

exports:让外部能用,但只给 public

module-info.ja va 里写一句 exports com.example.api;,意思很简单:其他模块可以编译和运行时使用这个包里的 public 类及其 public 成员

  • 其他模块能 new 这个包里的 public 类,能调用它的 public 方法,能读写它的 public 字段。
  • 但如果一个 public class User 里,字段 name 是包私有(没写 public),那其他模块依然碰不到它——编译期报错,运行期也过不去。
  • 哪怕你用反射 field.setAccessible(true),也会直接抛出 IllegalAccessException。因为 exports 只管“能不能用”,不管“能不能反射”。

简单一句话:exports 只开了一扇门,但门里只有 public 的东西能见光。

opens:给反射开绿灯,连 private 都放行

如果你的类需要被 Spring、Hibernate、JUnit 这类框架通过反射操作非 public 成员,那就必须用 opens 明确授权。

  • opens com.example.model; → 所有模块都能通过反射访问这个包里所有类的所有成员,包括 private 字段和方法。
  • opens com.example.config to spring.core; → 只对 spring.core 一个模块开放,安全性高得多。
  • 需要留意的是:opens 不影响编译期的可见性。换句话说,它不会让其他模块在写代码时就能直接引用包私有的类;它只在运行期给反射开了绿灯。

package-private 类:连模块的门都出不去

如果一个类没有 public 修饰符(也就是包私有),就算你 exports 了整个包,其他模块也根本看不见这个类。这不是反射的问题,是类加载器压根儿不知道有这个类存在。

  • 编译时直接报 cannot find symbol
  • 运行时抛出 NoClassDefFoundErrorIllegalAccessError
  • 模块系统不会“穿透”包级别的封装
  • 如果你确实想复用某个实现但又不想暴露为 public API,可以考虑用 provides ... with + service interface 的模式,把实现类留在包私有里。

常见误判与调试提示

遇到“明明 exports 了却访问不到”这种问题,不要慌,先检查这几个地方:

  • 目标类或字段是不是 public?不是的话,exports 帮不上忙,得用 opens
  • 是否用了 --illegal-access=deny(JDK 16+ 默认设置)?没有 opens 就直接失败,连警告都不给。
  • IDE 可能不报错,因为编译器只校验 exports,真正的拦截发生在 JVM 启动时。建议用 jlink 或真实模块路径来测试。
  • 第三方库(比如 commons-lang3)如果没有 module-info.class,它会变成“自动模块”,exports 规则对它不生效。开发环境下可以用 --add-opens 临时绕过,但生产环境别这么干。

Ja va 9模块化系统(JPMS):控制对象变量跨包访问权限指南

本文转载于:https://www.php.cn/faq/2443663.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注