什么是Java 9中的开放模块以及如何使用它
模块与open关键字之前和之后有什么区别?
例如:
open module foo { } module foo { }
为了提供对模块的reflection访问,Java 9引入了open关键字。
您可以在模块声明中使用open关键字创建开放模块。
一个开放模块允许对其他模块的所有包进行reflection访问。
例如,如果你想使用一些严重依赖于reflection的框架,比如Spring,Hibernate等,你可以使用这个关键字,为它启用reflection访问。
您可以使用包声明中的opens语句为模块的指定包启用reflection访问:
module foo { opens com.example.bar; }
或在模块声明中使用open关键字:
open module foo { }
但请记住,你不能将它们结合起来:
open module foo { opens com.example.bar; }
编译时错误的结果。
希望能帮助到你。
有点指令的背景。 模块系统在Breaking encapsulation部分中说明
有时需要违反模块系统定义的访问控制边界,并由编译器和虚拟机强制执行,以便允许一个模块访问另一个模块的某些未导出类型。 这可能是期望的,以便例如启用内部类型的白盒测试,或者将不受支持的内部API暴露给依赖于它们的代码。 在编译时和运行时 ,可以使用
--add-exports
选项来执行此操作。
命令行选项相当于例如: –
module java.logging { exports java.util.logging; }
--add-exports
选项允许访问指定包的公共类型。
虽然此后,
有时需要更进一步,并通过核心reflectionAPI的setAccessible方法启用对所有非公共元素的访问。 可以在运行时使用
--add-opens
选项来执行此操作。
此命令行选项等效于: –
module jdk.unsupported { opens sun.misc; }
相反,普通的命名模块使用模块声明明确定义为: –
module foo { }
这些被称为显式模块 。 显式模块可以使用如上所述的包上的指令,例如export
/ open
包以提供对其各自公共成员和类的reflection访问。
另一方面, OPEN
模块是一个
模块没有声明任何打开的包,但生成的模块被视为所有包都打开 。
这样它就可以在运行时向所有模块的包中的类型授予访问权,就好像所有包都被导出一样,这意味着可以使用字节码或reflection来访问所有包中的每个包的类或成员 。 具有setAccessible
或MethodHandles.privateLookupIn
的reflectionAPI允许深度reflection ,因此简而言之, 您可以反映所有包中所有类的所有成员 。 这也解释了为什么编译器在模块已经打开时不允许对包打开指令的原因。