什么是Java 9中的开放模块以及如何使用它

use*_*774 21 java java-9 java-module module-info

模块与open关键字之前和之后有什么区别?
例如:

open module foo {
}

module foo {
}
Run Code Online (Sandbox Code Playgroud)

Mic*_*zyk 21

为了提供对模块的反射访问,Java 9引入了open关键字.

您可以在模块声明中使用open关键字创建开放模块.

一个开放模块允许对其他模块的所有包进行反射访问.

例如,如果你想使用一些严重依赖于反射的框架,比如Spring,Hibernate等,你可以使用这个关键字,为它启用反射访问.

您可以使用包声明中的opens语句为模块的指定包启用反射访问:

module foo {
    opens com.example.bar;
}
Run Code Online (Sandbox Code Playgroud)

或在模块声明中使用open关键字:

open module foo {
}
Run Code Online (Sandbox Code Playgroud)

但请记住,你不能将它们结合起来:

open module foo {
    opens com.example.bar;
}
Run Code Online (Sandbox Code Playgroud)

编译时错误的结果.

希望能帮助到你.


Nam*_*man 7

有点指令的背景.的模块系统中的状态断封装

有时需要违反模块系统定义的访问控制边界,并由编译器和虚拟机强制执行,以便允许一个模块访问另一个模块的某些未导出类型.这可能是合乎需要的,例如,为了启用内部类型的白盒测试,或者将不支持的内部API暴露给依赖于它们的代码.--add-exports可以在编译时和运行时使用该 选项来执行此操作.

命令行选项等同于例如: -

module java.logging {
    exports java.util.logging;
}
Run Code Online (Sandbox Code Playgroud)

--add-exports选项允许访问指定包的公共类型.


虽然此后,

有时需要更进一步,并通过核心反射API的setAccessible方法启用对所有非公共元素的访问.--add-opens可以在运行时使用该选项来执行此操作.

此命令行选项等效于: -

module jdk.unsupported  {
   opens sun.misc; 
}
Run Code Online (Sandbox Code Playgroud)

相比之下,普通的命名模块使用模块声明明确定义为: -

module foo { }
Run Code Online (Sandbox Code Playgroud)

这些被称为显式模块.显式模块可以使用如上所述的包上的指令,例如export/ openpackages,以提供对其各自公共成员和类的反射访问.


另一方面,OPEN模块是

模块没有声明任何打开的包,但生成的模块被 视为所有包都打开.

这样它就可以在运行时向所有模块的包中的类型授予访问权限,就好像所有包都被导出一样,这意味着可以使用字节码或反射来访问所有包中的每个包的类或成员.具有setAccessibleMethodHandles.privateLookupIn允许深度反射的反射API ,因此简而言之,您可以反映所有包中所有类的所有成员.这也解释了为什么编译器在模块已经打开时不允许对包打开指令的原因.