8

为了了解我们拥有的类别:

  • 平台显式模块
  • 应用显式模块
  • 开放模块
  • 自动模块
  • 未命名的模块

类路径中的所有类和 jar 都将成为未命名模块的一部分。但为什么这是我们需要的?与自动模块相比,优势在哪里?我可以“要求”那些该死的遗留罐子将它们变成一个自动模块。我没有把所有东西都包括进去吗?

4

2 回答 2

10

至少有两个原因:

  • 就像常规模块一样,自动模块在模块系统的某些检查中是可疑的,例如不拆分包。由于类路径上的 JAR 可以(并且偶尔会)拆分包,因此对它们进行检查将是向后不兼容的,并且会破坏许多应用程序。
  • 未命名的模块可以读取所有平台模块,而自动模块只能读取那些进入模块图的模块。这意味着需要java.desktop模块(例如)的 JAR 将在类路径中工作,但不能从模块图中工作,除非java.desktop也将其放入图中(通过依赖项或--add-modules)。

我现在没有时间检查第二个,但这就是模块系统状态所说的:

因此,在解析模块图后,自动模块会读取所有其他命名模块,无论是自动的还是显式的

解析适用于声明的依赖项,自动模块声明无。

于 2017-07-18T12:41:37.130 回答
0

除了接受的答案中列出的项目之外,还有一个区别:未命名的模块可以访问 Java 附带的所有模块包,即使它们没有被导出。只要类是公共的,访问就可以工作 - 与 Java 9 之前相同。但是一旦从模块路径运行 jar,它将只能访问导出的包。

例如,如果有些.jar人有这个代码:

com.sun.jmx.remote.internal.ArrayQueue c = new com.sun.jmx.remote.internal.ArrayQueue(10);

当放置在类路径上时,它将正常运行而没有任何警告,但是当从模块路径(作为自动模块)运行时,它将在运行时失败:

Exception in thread "main" java.lang.IllegalAccessError: class test1.C 
(in module test1) cannot access class com.sun.jmx.remote.internal.ArrayQueue 
(in module java.management) because module java.management does not export 
com.sun.jmx.remote.internal to module test1

请注意,这与众所周知的非法反射访问警告不同,后者是关于使用反射访问私有字段或方法。在这里,我们静态(非反射)访问公共类(但来自非导出包)。

于 2019-11-15T02:35:09.020 回答