31

当我编译一个依赖于我之前编译过的其他模块的模块时,我必须指定该--module-path <directory>选项。这使得我依赖的模块可见。

但同时我也想让一些非模块化的 Jar 文件可见。但是,如果不使它们成为自动模块并仅指定--class-path some.jar旁边的右侧--module-path <directory>,那么javac似乎会忽略 claspath 并抛出“未找到包 yyy”和其他“未找到”错误。

我可以理解在同一(编译)时间使用--class-pathand是非法的,但javac不会以任何方式警告我。--module-path

4

2 回答 2

47

您可以并行使用类路径和模块路径,但需要考虑一些细节。

依赖模块路径 ~> 类路径

显式模块(在模块路径上带有模块描述符的 JAR)无法读取未命名的模块(在类路径上的 JAR) - 这样做是为了防止模块化 JAR 依赖于“类路径的混乱”。

由于一个模块必须要求它的所有依赖项,并且这些依赖项只能由其他命名模块(即不是类路径上的 JAR)来实现,因此模块化 JAR 的所有依赖项都必须放在模块路径上。是的,即使是非模块化 JAR,它们也会变成自动模块

有趣的是,自动模块可以读取未命名的模块,因此它们的依赖关系可以在类路径上。

依赖类路径 ~> 模块路径

如果您编译非模块化代码或从非模块化 JAR 启动应用程序,模块系统仍在发挥作用,因为非模块化代码不表达任何依赖关系,它不会从模块路径解析模块。

因此,如果非模块化代码依赖于模块路径上的工件,您需要使用选项手动添加--add-modules它们。不一定全部,只是那些你直接依赖的(模块系统将引入传递依赖) - 或者你可以使用ALL-MODULE-PATH(查看链接的帖子,它更详细地解释了这一点)。

于 2017-09-18T22:52:42.963 回答
10

我相信同时使用--classpathand--module-path选项并不违法即使您没有明确指定默认为当前目录的类路径,也可以同时使用两者。

来自javac -help消息和javac 工具文档的详细信息-

--module-path <path>, -p <path>

指定在哪里可以找到应用程序模块

--class-path <path>, -classpath <path>, -cp <path>

指定在哪里可以找到用户类文件和注释处理器

如果--class-path-classpath-cp 未指定,则用户类路径是当前目录


编辑:感谢@MouseEvent,我可能错过了问题中的部分

但是,如果不使它们成为自动模块,而只是在 --module-path 旁边指定 --class-path some.jar ,那么 javac 似乎会忽略 claspath 并抛出“未找到包 yyy”和其他“未找到” “错误。

如果您不让它们自动运行,它会被视为模块系统的未命名模块,并且 -

事实上,命名模块甚至不能声明对未命名模块的依赖。这种限制是有意的,因为允许命名模块依赖于类路径的任意内容会使可靠的配置变得不可能。

此外,未命名模块导出其所有包,因此自动模块中的代码将能够访问从类路径加载的任何公共类型。

但是使用类路径中类型的自动模块不能将这些类型暴露给依赖它的显式模块,因为显式模块不能声明对未命名模块的依赖关系。

如果显式模块中的代码com.foo.app引用了一个公共类型com.foo.bar,例如,并且该类型的签名引用了仍在类路径上的一个 JAR 文件中的类型,那么其中的代码com.foo.app将无法访问该类型,因为 com.foo.app不能依赖于未命名的模块。

这可以通过com.foo.app暂时将其视为自动模块来解决,以便其代码可以从类路径访问类型,直到类路径上的相关 JAR 文件可以被视为自动模块或转换为显式模块。

于 2017-09-18T21:35:36.237 回答