在 Java 9 中,需求语句和需要传递语句之间有什么区别?

模块声明中的必需模块语句和要求传递模块语句之间有什么区别?

例如:

module foo {
    requires java.base;
    requires transitive java.compiler;
}

答案 1

可读性回顾

如果模块酒吧模块喝水,那么模块系统...requires

  • 强制存在饮料(称为可靠配置))
  • 允许酒吧阅读饮料(称为可读性))
  • 允许 bar 中的代码访问饮料中导出的包中的公共类(称为辅助功能))

如果酒吧 - 饮料必须存在,可以阅读和访问,也会发生完全相同的情况。事实上,对于酒吧和饮料,关键字不会改变任何东西。requires transitive drinktransitive

隐含的可读性

依赖于酒吧模块是受以下因素影响的模块: 任何读取酒吧的模块也可以阅读饮料。换句话说,饮料的可读性是隐含的(这就是为什么这被称为隐含的可读性)。结果是客户可以访问饮料的类型。transitive

因此,如果 和 ,则客户可以阅读饮料,即使它没有明确依赖于它。bar requires transitive drinkcustomer requires bar

使用案例

但是为什么?假设您有一个模块,其公共 API 接受或返回另一个模块的类型。假设 bar 模块公开返回 的实例,一个来自 drink 模块的接口:Drink

// in module _bar_
public class Bar {

    // `Drink` comes from the module _drink_,
    // which _bar_ requires
    public Drink buyDrink() { /* ... */ }

}

在此示例中,bar 使用常规饮料。现在说,客户依赖于bar,因此其所有代码都可以调用。但是,当它发生时会发生什么呢?requiresBar::buyDrink

模块系统抱怨客户不读取饮料,因此无法访问 。为了解决这个问题,客户还必须依靠饮料。真是一件苦差事!你不能立即使用的酒吧有多无用?Drink

customer requires bar requires drink - but how does customer read drink?

出于这个原因,引入了隐含的可读性:使一个在自己的公共API中使用另一个模块类型的模块立即可用,不需要调用方进行搜索并需要所有相关的模块。

因此,如果,客户可以开始购买饮料而不必 - 就足够了。正如它应该的那样。bar requires transitive drinkrequire drinkrequire bar


答案 2

两者之间的主要区别在于从一个模块到另一个模块的访问。

如果一个模块导出的包包含一个类型的签名引用第二个模块中的包,则第一个模块的声明应包括对第二个模块的依赖关系。这将确保依赖于第一个模块的其他模块将自动能够读取第二个模块,从而访问该模块导出的包中的所有类型。requires transitive


因此,让我们说说您的用例:-

module foo {
    requires java.base;
    requires transitive java.compiler;
}

~> 任何依赖于该模块的模块都将自动读取该模块foojava.compiler

~> 另一方面,要访问模块,他们必须再次指定一个子句。java.baserequires

module bar {
    requires foo; // java.compiler is available to read
    requires java.base; // still required
}

推荐