作为核心 Jigsaw
project是Java模块系统,能够限制对特定模块中特定程序元素(类,方法和字段)的访问是很好的。
当模块中的某些元素对于此模块基本上是公共的时,它可能会有所帮助,但不应在此模块外部访问。
所以我在谈论“package-local”之后的下一级访问,可以命名为“module-local”。
不过简单看一下 拼图规则 早期的规格并没有帮助我弄清楚这种功能。进一步来说 这个 Modifier
规范 不包含任何新元素。
那么在未来的Java 9中还有其他任何可能吗?
一个 public
元素(即,一个类,接口,方法或字段)
非导出包实际上是“模块本地”。它将是
可以访问模块中的所有其他代码,但不能从外部访问
模块。
无法在导出的包中声明模块本地元素。
一个 public
导出包的元素可以从外部访问
在这个模块中,一个package-private元素仍然是package-private,而且还有
这两种模式之间没有元素级访问模式。我们可以定义一个
新的这种模式,但我们看到它很少引人注目的用例,
此外,在粒度上在JVM中实现模块化访问控制
比导出的包更精细会带来显着的性能
成本。
简答
当模块中的某些元素对于此模块基本上是公共的时,它可能会有所帮助,但不应在此模块外部访问。
这是不可能的。 (仅使用模块系统的方法 - 有一种解决方法。)
答案很长
解释在该术语内 无障碍:
Java编译器和虚拟机将一个模块中的公共类型视为一个模块 无障碍 仅在第一模块可由第二模块读取时,在上面定义的第一模块中,并且第一模块导出该包,则通过代码在一些其他模块中。 [...]
以这种方式无法访问的跨模块边界引用的类型不可用,就像私有方法或字段不可用一样:任何使用它的尝试都将导致编译器报告错误,或者 IllegalAccessError
被Java虚拟机抛出,或者被抛出 IllegalAccessException
被反射运行时API抛出。 [...]
如果在这种意义上可以访问其封闭类型,并且成员本身的声明也允许访问,则可以访问跨模块边界引用的方法或字段。
虽然编译器/ JVM认为类型可访问,但是有多种方式可以准确地导出包的方式和对象 没有其他机制适用。它的成员和Jigsaw之前一样容易接近。
这意味着无法在模块中看到可访问类型的成员(这将需要 public
)但不在它之外(因为可访问类型的公共成员是可访问的)。
解决方法
那么在未来的Java 9中还有其他任何可能吗?
是。 :)
您可以拥有一个公共界面 Global
在导出的包中定义要导出到世界的方法。然后有一个接口或一个类 Local
延伸 Global
并添加所需的所有成员。关键是 Local
必须 不 在一个出口包!
现在,如果您的模块的API仅返回 Global
-s但从不接受它们作为方法参数,你很高兴。只要确保你在内部总是使用 - 并且可能被投射到 - Local
。
如果你也接受 Global
-s你必须清楚地记录这些只能是你的API返回的实例(即不允许用户创建自己的实现)。这可能听起来令人望而却步,但如果您认真考虑原始请求,它将具有相同的特征。