Java 9:可以在模块路径上有 2 个同名的模块

2022-09-04 21:05:07

是否可以在模块路径上有 2 个名称完全相同(但内容略有不同)的模块?

据我所知,Java 9编译器并没有抱怨它。我有2个模块声明如下:

module com.dj.helper {
    exports com.dj.helper;
}

两者都包含包,但在包内内容是不同的。然后在我的主应用程序中,我希望导入此模块:com.dj.helper

module com.dj {
    requires com.dj.helper;
}

两个同名的模块都在我的模块路径上。

我希望在编译我的模块时,编译器会抱怨同一个模块存在两次,但事实并非如此。这是否意味着您可以在模块路径上有2个版本的同一jar,而Java将不知道该使用哪一个?com.dj


答案 1

在模块路径上的同一目录中不可能有两个同名的模块。官方文档并没有将这些信息放在一个特别突出的位置 - 它是ModuleFinder::的Javadoc,它给出了它:

如果目录包含多个具有相同名称的模块,则会出现错误。

为模块系统创建了一个小型演示项目,它通过创建同一模块的两个版本来涵盖这种情况......

jar --create
    --file mods/monitor.observer.beta-1.0.jar
    --module-version 1.0
    -C classes/monitor.observer.beta .
jar --create
    --file mods/monitor.observer.beta-2.0.jar
    --module-version 2.0
    -C classes/monitor.observer.beta .

...然后在下一次编译中引用该文件夹...

javac
    --module-path mods
    -d classes/monitor.statistics
    $(find monitor.statistics -name '*.java')

...这按预期会导致以下错误消息:

error: duplicate module on application module path
module in monitor.observer.beta
1 error

请注意,我在同一目录中说过。跨目录可以有多个模块。

是的

模块系统仅在目录中强制实施唯性。再次来自ModuleFinder::of(强调我的):

模块查找器通过按数组索引顺序搜索每个目录、分解模块或打包模块来查找模块。它查找具有给定名称的模块的第一个匹配项,并忽略序列后面出现的该名称的其他模块

这样就可以在不同的目录中使用相同的模块。


答案 2

模块系统的 JEP 261 描述模块路径如下:

模块路径是一个序列,其每个元素要么是模块定义,要么是包含模块定义的目录。每个模块定义是

  • 模块工件,即包含已编译模块定义的模块化 JAR 文件或 JMOD 文件,或者

  • 一个分解模块目录,其名称按照约定是模块的名称,其内容是对应于包层次结构的“分解”目录树。

然后,它描述了模块解析机制:

在模块路径中搜索具有特定名称的模块时,模块系统将采用该名称的模块的第一个定义。版本字符串(如果存在)将被忽略;如果模块路径的元素包含具有相同名称的多个模块的定义,则解析失败,编译器、链接器或虚拟机将报告错误并退出。构建工具和容器应用程序负责配置模块路径,以避免版本冲突;解决版本选择问题不是模块系统的目标。

如前所述,这意味着仅当同一目录中存在两个具有相同名称的模块时,编译器才会报告。


推荐