模块声明中 需要 和 需要传递 模块语句的区别是什么?<登记/>
例如:
module foo {
requires java.base;
requires transitive java.compiler;
}
答案 0 :(得分:62)
如果模块 bar requires
模块饮用,那么模块系统......
如果 bar requires transitive drink
- 饮料必须存在,可以阅读和访问,则完全相同。事实上,对于 bar 和 drink ,transitive
关键字不会改变任何内容。
模块取决于 bar 是受transitive
影响的模块:任何读取 bar 的模块也可以读取饮。换句话说, drink 的可读性是暗示(这就是为什么这称为implied readability)。结果是客户可以访问饮料的类型。
因此,如果bar requires transitive drink
和customer requires bar
,则客户可以阅读 drink ,即使它没有明确依赖它。
但为什么呢?想象一下,你有一个模块,其公共API接受或返回另一个模块的类型。假设 bar 模块公开返回Drink
的实例,这是来自饮料模块的界面:
// in module _bar_
public class Bar {
// `Drink` comes from the module _drink_,
// which _bar_ requires
public Drink buyDrink() { /* ... */ }
}
在此示例中, bar 使用常规requires
进行饮料。现在说, customer 依赖于 bar ,所以它的所有代码都可以调用Bar::buyDrink
。但是当它发生时会发生什么?
模块系统抱怨客户没有读取饮料,因此无法访问Drink
。要解决此问题,客户还必须依赖饮料。真是个琐事!你不能马上使用的酒吧是多么无用?
出于这个原因,引入了隐含的可读性:使模块在其自己的公共API中使用另一个模块的类型立即可用,而不需要要求调用者追捕并需要所有涉及的模块。
因此,如果bar requires transitive drink
,客户可以开始购买饮品而无需require drink
- require bar
就足够了。应该如此。
答案 1 :(得分:6)
两者之间的主要区别在于从属模块的访问权限。
如果一个模块导出包含其签名类型的包 指的是第二个模块中的包然后声明的 第一个模块应该包括
requires transitive
依赖 第二。这个 将确保依赖于其他模块 第一个模块将自动读取第二个模块 , 因此,访问该模块导出的包中的所有类型。
因此,请告诉您的用例: -
module foo {
requires java.base;
requires transitive java.compiler;
}
〜&GT;依赖于foo
模块的任何模块都将自动读取java.compiler
模块
〜&GT;另一方面,要访问模块java.base
,他们必须再次指定requires
子句。
module bar {
requires foo; // java.compiler is available to read
requires java.base; // still required
}
答案 2 :(得分:5)
requires
描述了解决模块如何相互依赖的过程。
'require'指令(不论'传递')表达了这一点 一个模块依赖于其他模块。 的效果 'transitive'修饰符会导致其他模块依赖 另一个模块 。如果模块M'需要传递N',那么不仅如此 M取决于N,但依赖于M的任何模块也依赖于 N.这允许M被重构以便其部分或全部内容 可以移动到新模块N而不破坏具有的模块 '需要M'指令。
简而言之:
requires
- M模块依赖于其他模块N。
requires transitive
- 其他模块隐含地取决于其他模块。例如:,如果M模块依赖于N,而其他模块P依赖于M.那么,它也隐含地依赖于N.
答案 3 :(得分:2)
尼古拉已经详细解释过。我只是在这里给出一个JDK代码的具体示例。考虑jdk.scripting.nashorn模块。该模块的模块信息如下:
它有这一行:
requires transitive java.scripting;
这是因为jdk.scripting.nashorn模块在jdk.scripting.api.scripting包中自己的API接受/返回javax.script模块的java.scripting包中的类型。所以jdk.scripting.nashorn告诉JMPS,任何依赖于jdk.scripting.nashorn的模块都会自动依赖于java.scripting模块!
现在,相同的jdk.scripting.nashorn模块使用以下行:
requires jdk.dynalink;
另一个模块jdk.dynalink。这是因为jdk.scripting.nashorn模块中导出的包的 none (&#34; API&#34;)使用了jdk.dynalink模块中的类型。 jdk.scripting.nashorn对jdk.dynalink的使用纯粹是一个实现细节。
答案 4 :(得分:1)
Java 9 Java语言规范以非常简单的术语解释它。来自Module Dependences的部分:
requires
指令指定当前模块具有依赖关系的模块的名称。...
requires
关键字后面可能跟修饰符transitive
。 这会导致requires
当前模块的任何模块隐式声明对requires transitive
指令指定的模块的依赖。
换句话说:
requires
模块Y,requires transitive
模块Z,requires
模块Z。答案 5 :(得分:0)
术语辅助功能含糊不清:您可以访问对象而无需访问其类型。如果一个对象的类型为T,它位于一个未导出的包中,并且一个“导出的”代码有一个方法返回一个T ...那么当调用这个方法时,你得到一个关于这个T对象的句柄(你可以调用任何与代码已知类型相关的方法。
可读性也不明确:它并不意味着你的ClassLoader总是无法加载(未导出的)T类。