为什么要从 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 BatemanMichael 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 文件的构建脚本:

  1. 它编译.java个文件(我们有module-info.java定义opens com.foo.abc;com/foo/abc目录("package")不存在)
  2. 它创建 com/foo/abc 目录
  3. 它复制 config_dev.properties 文件,在这一步决定我们构建的环境 (PROD/TEST/DEV)
  4. JAR文件打包完成,包含字节码和资源。

如果 non-existing 目录的 opens 不被允许,第 1 步将失败。但它只在编译时给出警告,这没问题。