- 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.4 Requiring Modules
Let us make a new module v2ch09.requiremod in which a program uses a JOptionPane to show the “Hello, Modular World!” message:
package com.horstmann.hello; import javax.swing.JOptionPane; public class HelloWorld { public static void main(String[] args) { JOptionPane.showMessageDialog(null, "Hello, Modular World!"); } }
Now compilation fails with this message:
error: package javax.swing is not visible (package javax.swing is declared in module java.desktop, but module v2ch09.requiremod does not read it)
The JDK has been modularized, and the javax.swing package is now contained in the java.desktop module. Our module needs to declare that it relies on that module:
module v2ch09.requiremod { requires java.desktop; }
It is a design goal of the module system that modules are explicit about their requirements, so the virtual machine can ensure that all requirements are fulfilled before starting a program.
In the preceding section, the need for explicit requirements did not arise because we only used the java.lang and java.io packages. These packages are included in the java.base module which is required by default.
Note that our v2ch09.requiremod module lists only its own module requirements. It requires the java.desktop module so that it can use the javax.swing package. The java.desktop module itself declares that it requires three other modules, namely java.datatransfer, java.prefs, and java.xml.
Figure 9.1 shows the module graph whose nodes are modules. The edges of the graph—the arrows joining nodes—are either declared requirements or the implied requirement on java.base when none is declared.
Figure 9.1 The module graph of the Swing “Hello, Modular World” application
You cannot have cycles in the module graph—that is, a module cannot directly or indirectly require itself.
A module does not automatically pass on access rights to other modules. In our example, the java.desktop module declares that it requires java.prefs, and the java.prefs module declares that it requires java.xml. That does not give java.desktop the right to use packages from the java.xml module. It needs to explicitly declare that requirement. In mathematical terms, the requires relationship is not “transitive.” Generally, this behavior is desirable because it makes requirements explicit, but as you will see in Section 9.11, “Transitive and Static Requirements,” on p. 523, you can relax it in some cases.