为什么从Java模块中打开一个不存在的包?

Bar*_*jeu 5 java jls java-module

JLS 11 “ 7.7.2。导出和打开的包”说:

允许opens指定一个与当前模块关联的编译单元未声明的包。

这将是什么情况?为什么需要这个?

Bar*_*jeu 3

感谢Alan BatemanMichael Easter的解释,我可以想到一些现实的场景。

首先,正如 Alan 和 Michael 所解释的:当我们将资源保存在其中时,JLS 允许在没有 Java 类型的情况下“打开”目录。因此,对于我们来说,这些是“资源目录”,但 JLS 将其命名为package which is not declared by a compilation unit. 这甚至不是“允许”的问题,而是“必须”的问题。如果没有opens资源目录 ( ) 指令com/foo/abc,另一个模块无法读取这样的资源:

InputStream is = ClassLoader.getSystemResourceAsStream("com/foo/abc/config.properties");
Run Code Online (Sandbox Code Playgroud)

其次,我写这个问题主要是因为我很困惑,它opens允许指定甚至不存在的“包”(目录),尽管它给出警告,但编译成功。我可以想到模块化 JAR 文件的构建脚本背后的可能场景:

  1. 它编译.java文件(我们已经module-info.java定义opens com.foo.abc;并且com/foo/abc目录(“包”)不存在)
  2. 它创建com/foo/abc目录
  3. 它复制那里的config_dev.properties文件,在这一步决定我们构建什么环境(生产/测试/开发)
  4. JAR文件被打包,包含字节码和资源。

如果opens不允许使用不存在的目录,步骤 #1 将失败。但它只在编译时给出警告,这是可以的。