Java 9 中的“模块本地”访问行为简答题长答案解决方法

由于项目的核心是Java模块系统,因此能够限制对特定模块中特定程序元素(类,方法和字段)的访问会很好。Jigsaw

当模块中有一些元素本质上是此模块的公共元素,但不应在此模块外部访问时,这可能很有用。

因此,我说的是“包本地”之后的下一级访问,可以将其命名为“模块本地”。

然而,对Jigsaw规则和早期规范的简要了解并不能帮助我找到这种功能。更具体地说,修饰符规范不包含任何新元素。

那么在未来的Java 9中还有其他可能性吗?


答案 1

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

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


答案 2

简答题

当模块中有一些元素本质上是此模块的公共元素,但不应在此模块外部访问时,这可能很有用。

这是不可能的。(仅通过模块系统的方法 - 有一个解决方法。

长答案

解释在术语“可访问性”中

Java 编译器和虚拟机认为,只有当第一个模块可由第一个模块(如上所述)读取第一个模块时,一个模块中的包中的公共类型才能通过其他模块中的代码访问,并且第一个模块导出该包。[...]

跨模块边界引用的类型如果无法以这种方式访问,则与私有方法或字段不可用的方式相同:任何使用它的尝试都将导致编译器报告错误,或由 Java 虚拟机引发错误,或由反射运行时 API 引发错误。[...]IllegalAccessErrorIllegalAccessException

如果跨模块边界引用的方法或字段在此类意义上是可访问的,并且成员本身的声明也允许访问,则可访问该方法或字段。

虽然有不同的方法可以确切地将包导出给谁,但是一旦编译器/ JVM认为某个类型可访问,就没有其他机制适用。它的成员与Jigsaw之前一样容易访问。

这意味着没有办法让可访问类型的成员在模块中可见(这需要),但在模块之外却不可见(因为可访问类型的公共成员是可访问的)。public

解决方法

那么在未来的Java 9中还有其他可能性吗?

是的。:)

您可以在导出的包中具有一个公共接口,该接口定义要导出到世界的方法。然后,使用接口或类进行扩展,并添加所需的所有成员。关键是不能在导出的包中!GlobalLocalGlobalLocal

现在,如果模块的 API 只返回 -s,但从不接受它们作为方法参数,那么你就可以开始了。只要确保在内部你总是使用 - 也许投射到 - .GlobalLocal

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


推荐