What's the difference between requires and requires transitive module statements in module declaration?
For example:
module foo {
requires java.base;
requires transitive java.compiler;
}
If module bar requires
module drink, then the module system...
Exactly the same happens if bar requires transitive drink
- drink must be present, can be read and accessed. In fact, for bar and drink the transitive
keyword doesn't change anything.
The modules depending on bar are the ones that are impacted by transitive
: Any module that reads bar can also read drink. In other words readability of drink is implied (which is why this is called implied readability). A consequence is that customer can access drink's types.
So if bar requires transitive drink
and customer requires bar
, then customer can read drink even though it doesn't explicitly depend on it.
But why? Imagine you have a module whose public API accepts or returns another module's type. Let's say the bar module publicly returns instances of Drink
, an interface from the drink module:
// in module _bar_
public class Bar {
// `Drink` comes from the module _drink_,
// which _bar_ requires
public Drink buyDrink() { /* ... */ }
}
In this example, bar uses a regular requires
for drink. Now say, customer depends on bar, so all its code can call Bar::buyDrink
. But what happens when it does?
The module system complains that customer does not read drink and can hence not access Drink
. To fix that, customer would also have to depend on drink. What a chore! How useless is a bar that you can't use straight away?
For this reason, implied readability was introduced: to make a module that uses another module's types in its own public API instantly usable without requiring the caller to hunt down and require all involved modules.
So if bar requires transitive drink
, customer can start buying drinks without having to require drink
- require bar
suffices. As it should.