为什么要从 Java 模块打开一个不存在的包?
Why open a non-existing package from a Java module?
JLS 11 "7.7.2. Exported and Opened Packages" 说:
It is permitted for opens
to specify a package which is not declared by a compilation unit associated with the current module.
这会是什么情况?为什么需要这个?
感谢 Alan Bateman 和 Michael Easter 的解释,我能想到一些现实的场景。
首先,正如 Alan 和 Michael 所解释的那样:JLS 允许 "open" 目录没有 Java 类型,以应对我们在其中保留资源的情况。所以,对我们来说这些是 "resource directories",但 JLS 将其命名为 package which is not declared by a compilation unit
。这甚至不是 "allows" 的问题,而是 "must" 的问题。没有资源目录 (com/foo/abc
) 的 opens
指令,另一个模块无法读取这样的资源:
InputStream is = ClassLoader.getSystemResourceAsStream("com/foo/abc/config.properties");
其次,我写这个问题主要是因为我很困惑 opens
允许指定甚至 non-existing "packages" (目录),虽然它给出警告,但编译成功。
一个可能的场景,我可以想到模块化 JAR 文件的构建脚本:
- 它编译
.java
个文件(我们有module-info.java
定义opens com.foo.abc;
和com/foo/abc
目录("package")不存在)
- 它创建
com/foo/abc
目录
- 它复制
config_dev.properties
文件,在这一步决定我们构建的环境 (PROD/TEST/DEV)
- JAR文件打包完成,包含字节码和资源。
如果 non-existing 目录的 opens
不被允许,第 1 步将失败。但它只在编译时给出警告,这没问题。
JLS 11 "7.7.2. Exported and Opened Packages" 说:
It is permitted for
opens
to specify a package which is not declared by a compilation unit associated with the current module.
这会是什么情况?为什么需要这个?
感谢 Alan Bateman 和 Michael Easter 的解释,我能想到一些现实的场景。
首先,正如 Alan 和 Michael 所解释的那样:JLS 允许 "open" 目录没有 Java 类型,以应对我们在其中保留资源的情况。所以,对我们来说这些是 "resource directories",但 JLS 将其命名为 package which is not declared by a compilation unit
。这甚至不是 "allows" 的问题,而是 "must" 的问题。没有资源目录 (com/foo/abc
) 的 opens
指令,另一个模块无法读取这样的资源:
InputStream is = ClassLoader.getSystemResourceAsStream("com/foo/abc/config.properties");
其次,我写这个问题主要是因为我很困惑 opens
允许指定甚至 non-existing "packages" (目录),虽然它给出警告,但编译成功。
一个可能的场景,我可以想到模块化 JAR 文件的构建脚本:
- 它编译
.java
个文件(我们有module-info.java
定义opens com.foo.abc;
和com/foo/abc
目录("package")不存在) - 它创建
com/foo/abc
目录 - 它复制
config_dev.properties
文件,在这一步决定我们构建的环境 (PROD/TEST/DEV) - JAR文件打包完成,包含字节码和资源。
如果 non-existing 目录的 opens
不被允许,第 1 步将失败。但它只在编译时给出警告,这没问题。