"Module local" Java 9 中的访问行为

"Module local" access behaviour in Java 9

由于 Jigsaw 项目的核心是 Java 模块系统,如果能够限制对特定程序元素(类、方法和字段)的访问,那就太好了) 仅在特定模块内。

如果模块中有一些元素本质上是该模块的 public,但不应在该模块外访问,这可能会有所帮助。

所以我说的是“package-local”之后的下一个访问级别,可以命名为“module-local”。

然而 Jigsaw rules and early specs didn't help me to find out such kind of functionality. More specifically this Modifier specification 的简要浏览不包含任何新元素。

那么以后有没有其他的可能Java9?

简答

It can be helpful when there are some elements in module which are essentially public for this module, but shouldn't be accessible outside this module.

那是不可能的。 (单独使用模块系统 - 有一个解决方法。)

长答案

解释在术语Accessibility中:

The Java compiler and virtual machine consider the public types in a package in one module to be accessible by code in some other module only when the first module is readable by the second module, in the sense defined above, and the first module exports that package. [...]

A type referenced across module boundaries that is not accessible in this way is unusable in the same way that a private method or field is unusable: Any attempt to use it will cause an error to be reported by the compiler, or an IllegalAccessError to be thrown by the Java virtual machine, or an IllegalAccessException to be thrown by the reflective run-time APIs. [...]

A method or field referenced across module boundaries is accessible if its enclosing type is accessible, in this sense, and if the declaration of the member itself also allows access.

虽然有不同的方法可以确切地说明如何以及向谁导出包,但一旦 compiler/JVM 认为类型可访问 就没有其他机制适用 。它的成员与 Jigsaw 之前一样易于访问。

这意味着无法让可访问类型的成员在模块内可见(这需要 public)但在模块外不可见(因为可访问类型的 public 成员可以访问)。

解决方法

So is any other possibility to do it in future Java 9?

是的。 :)

您可以在导出包中有一个 public 接口 Global,它定义了您想要导出到世界的方法。然后有一个接口或 class Local 扩展 Global 并添加所有你想要的成员。关键是 Local 必须 而不是 在导出包中!

现在,如果您的模块的 API 只有 returns Global-s 但从不接受它们作为方法参数,那么您就可以开始了。只要确保在内部你总是使用 - 并且可能转换为 - Local.

如果您还接受 Global-s,您必须清楚地记录这些只能是您的 API 返回的实例(即不允许用户创建她自己的实现)。这听起来可能令人望而却步,但如果您认真考虑您最初的请求,它会具有相同的特征。

一个public元素(,一个class,接口,方法或字段)在一个 未导出的包实际上是“本地模块”。这将是 模块中的所有其他代码都可以访问,但不能从模块外部访问 模块。

无法在导出包中声明模块本地元素。 可以从外部访问导出包的 public 元素 模块,一个包私有的元素仍然是包私有的,并且有 这两种模式之间没有元素级访问模式。我们可以定义一个 新的这种模式,但我们已经看到很少有令人信服的用例,而且, 此外,在 JVM 中以粒度实现模块化访问控制 比出口包装更精细会带来显着的性能 成本。