发布于2026-07-06 阅读(0)
扫一扫,手机访问
今天聊聊 Ja va 9 模块化系统里一个特别容易让人懵圈的问题——它到底控制的是什么东西的访问权限?
先说一个核心判断:JPMS 从来不直接管什么“对象变量”能不能跨包访问。它管的是跨模块的访问权限,具体来说,是一个模块里的包、类、成员,能不能被另一个模块看到、用到。至于同一个模块里不同包之间怎么访问,不好意思,这事依然归传统的 public、protected、包私有、private 这些老伙计管。模块系统只会在模块边界上站岗——当外部模块的代码试图访问你的内部时,它才会出手。
在 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 的东西能见光。
如果你的类需要被 Spring、Hibernate、JUnit 这类框架通过反射操作非 public 成员,那就必须用 opens 明确授权。
opens com.example.model; → 所有模块都能通过反射访问这个包里所有类的所有成员,包括 private 字段和方法。opens com.example.config to spring.core; → 只对 spring.core 一个模块开放,安全性高得多。opens 不影响编译期的可见性。换句话说,它不会让其他模块在写代码时就能直接引用包私有的类;它只在运行期给反射开了绿灯。如果一个类没有 public 修饰符(也就是包私有),就算你 exports 了整个包,其他模块也根本看不见这个类。这不是反射的问题,是类加载器压根儿不知道有这个类存在。
cannot find symbolNoClassDefFoundError 或 IllegalAccessErrorprovides ... with + service interface 的模式,把实现类留在包私有里。遇到“明明 exports 了却访问不到”这种问题,不要慌,先检查这几个地方:
public?不是的话,exports 帮不上忙,得用 opens。--illegal-access=deny(JDK 16+ 默认设置)?没有 opens 就直接失败,连警告都不给。exports,真正的拦截发生在 JVM 启动时。建议用 jlink 或真实模块路径来测试。module-info.class,它会变成“自动模块”,exports 规则对它不生效。开发环境下可以用 --add-opens 临时绕过,但生产环境别这么干。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8