简答
当模块中有一些元素对于这个模块本质上是公共的,但不应该在这个模块之外访问时,它会很有帮助。
这是不可能的。(仅使用模块系统 - 有一种解决方法。)
长答案
解释在于术语Accessibility:
Java 编译器和虚拟机认为只有当第一个模块可以被第二个模块读取时,一个模块中的包中的公共类型才能被其他模块中的代码访问,在上面定义的意义上,并且第一个模块导出该包. [...]
以这种方式无法访问的跨模块边界引用的类型不可用,就像私有方法或字段不可用一样:任何尝试使用它都会导致编译器报告错误,或者IllegalAccessError
抛出Java 虚拟机,或者IllegalAccessException
由反射运行时 API 抛出。[...]
跨模块边界引用的方法或字段是可访问的,如果它的封闭类型在这个意义上是可访问的,并且如果成员本身的声明也允许访问。
虽然有不同的方式可以准确地导出包的方式和对象,但一旦编译器/JVM 认为类型可访问,则不会应用其他机制。它的成员与 Jigsaw 之前一样易于访问。
这意味着没有办法让可访问类型的成员在模块内可见(这将需要public
)但在模块外部不可见(因为可访问类型的公共成员是可访问的)。
解决方法
那么在未来的 Java 9 中还有其他可能吗?
是的。:)
您可以在导出的包中拥有一个公共接口,该接口Global
定义了您想要导出到世界的方法。Local
然后扩展一个接口或一个类Global
并添加所有你想要的成员。关键是Local
不能在导出的包中!
现在,如果您的模块的 API 只返回Global
-s 但从不接受它们作为方法参数,那么您就可以开始了。只要确保在内部你总是使用 - 并且可能转换为 - Local
。
如果您也接受Global
-s 您必须清楚地证明这些只能是您的 API 返回的实例(即不允许用户创建自己的实现)。这听起来可能令人望而却步,但如果您仔细考虑您的原始请求,它将具有相同的特征。