- 9.1 The Module Concept
- 9.2 Naming Modules
- 9.3 The Modular "Hello, World!" Program
- 9.4 Requiring Modules
- 9.5 Exporting Packages
- 9.6 Modular JARs
- 9.7 Modules and Reflective Access
- 9.8 Automatic Modules
- 9.9 The Unnamed Module
- 9.10 Command-Line Flags for Migration
- 9.11 Transitive and Static Requirements
- 9.12 Qualified Exporting and Opening
- 9.13 Service Loading
- 9.14 Tools for Working with Modules
9.11 Transitive and Static Requirements
In Section 9.4, “Requiring Modules,” on p. 508, you have seen the basic form of the requires statement. In this section, you will see two variants that are occasionally useful.
In some situation, it can be tedious for a user of a given module to declare all required modules. Consider, for example, the java.desktop module. It requires three modules: java.prefs, java.datatransfer and java.xml. The java.prefs module is only used internally. However, classes from java.datatransfer and java.xml appear in the public API, in methods such as
java.awt.datatransfer.Clipboard java.awt.Toolkit.getSystemClipboard() java.beans.XMLDecoder(org.xml.sax.InputSource is)
That is not something that a user of the java.desktop module should have to think about. For that reason, the java.desktop module declares the requirement with the transitive modifier:
module java.desktop { requires java.prefs; requires transitive java.datatransfer; requires transitive java.xml; . . . }
Any module that declares a requirement on java.desktop now automatically requires these two modules.
One compelling use of the requires transitive statement is an aggregator module—a module with no packages and only transitive requirements. One such module is the java.se module, declared like this:
module java.se { requires transitive java.compiler; requires transitive java.datatransfer; requires transitive java.desktop; . . . requires transitive java.sql; requires transitive java.sql.rowset; requires transitive java.xml; requires transitive java.xml.crypto; }
A programmer who isn't interested in fine-grained module dependencies can simply require java.se and get all modules of the Java SE platform.
Finally, there is an uncommon requires static variant that declares that a module must be present at compile time but is optional at runtime. There are two use cases:
To access an annotation that is processed at compile time and declared in a different module.
To use a class in a different module if it is available, and otherwise do something else, such as:
try { new oracle.jdbc.driver.OracleDriver(); . . . } catch (NoClassDefFoundError er) { Do something else }