Java 9 中什么是开放模块,如何使用它?

2022-09-01 06:02:06

前面有关键字的模块和没有关键字的模块有什么区别?例如:open

open module foo {
}

module foo {
}

答案 1

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

可以使用模块声明中的 open 关键字创建打开的模块。

开放模块向其他模块授予对其所有包的反射访问权限。

例如,如果要使用一些严重依赖反射的框架,例如Spring,Hibernate等,则可以使用此关键字为其启用反射访问。

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

module foo {
    opens com.example.bar;
}

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

open module foo {
}

但请记住,您不能将它们组合在一起:

open module foo {
    opens com.example.bar;
}

结果显示编译时错误。

希望它有帮助。


答案 2

对所讨论的指令有一点背景介绍。模块系统“中断封装”部分中的状态

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

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

module java.logging {
    exports java.util.logging;
}

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


虽然此后,

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

此命令行选项等效于例如:-

module jdk.unsupported  {
   opens sun.misc; 
}

相比之下,一个普通的命名模块是用模块声明显式定义的:-

module foo { }

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


另一方面,OPEN 模块是一个

不声明任何打开的包但生成的模块被视为所有包都已打开的模块

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


推荐