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;
}
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;
}
Primary difference between the two is the access of a dependent module from one to another.
So let's say for your use case :-
~> Any module that depends upon the
foo
module will automatically read thejava.compiler
module~> On the other hand to access the module
java.base
, they must specify arequires
clause again.requires
describes the process of resolution on how modules are dependent on each other.Quoting line
In short :
requires
- M module depends on some other module N.requires transitive
- additional modules implicitly depends on the other module. Eg:, If M module depends on N, and other module P depends on M. Then, it is implicitly dependent on N as well.The term accessibility is ambiguous: you can access objects without access to their type. If an object is of type T that lies in a package that is not exported and if an "exported" code has a method that returns a T ... Then when invoking this method you get a handle on this T object (and you can invoke on it any methods that pertains to any type known to your code).
readability is also ambiguous: it does not mean your ClassLoader will always be unable to load the (unexported) T class.
The Java Language Specification for Java 9 explains it in very simple terms. From the section on Module Dependences:
In other words:
requires
module Y,requires transitive
module Z,requires
module Z.Readability recap
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 thetransitive
keyword doesn't change anything.Implied readability
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
andcustomer requires bar
, then customer can read drink even though it doesn't explicitly depend on it.Use cases
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 this example, bar uses a regular
requires
for drink. Now say, customer depends on bar, so all its code can callBar::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 torequire drink
-require bar
suffices. As it should.Nicolai has explained in detail. I'm just giving a specific example from JDK code here. Consider the jdk.scripting.nashorn module. The module-info of this module is as follows:
http://hg.openjdk.java.net/jdk9/dev/nashorn/file/17cc754c8936/src/jdk.scripting.nashorn/share/classes/module-info.java
It has this line:
This is because jdk.scripting.nashorn module's own API in jdk.scripting.api.scripting package accepts/returns types from javax.script package of the java.scripting module. So jdk.scripting.nashorn tells the JMPS that any module that depends on jdk.scripting.nashorn automatically depends on java.scripting module as well!
Now, the same jdk.scripting.nashorn module uses this line:
for another module jdk.dynalink. That is because none of the exported packages (the "API") from jdk.scripting.nashorn module uses types from jdk.dynalink module. The use of jdk.dynalink by jdk.scripting.nashorn is purely an implementation detail.