19.3 Module Basics
Underlying the Java Module System is the concept of a module which is defined in the language and supported by the various JDK tools (such as javac, java, jar, and jdeps) and the Java runtime environment.
An understanding of packages is a prerequisite for understanding modules. The discussion of packages in §6.3, p. 326, is therefore highly relevant to this chapter. Going forward, we assume that creating and using packages in Java is well understood.
Module Declaration
A module declaration embodies the definition of a module that contains packages— that is, it specifies a module’s properties. A module declaration must specify the name of the module and can declare the following in its declaration:
- Dependencies the module has on other modules—that is, modules it requires to implement its functionality
- Packages it exports for other modules to use
- Packages it opens for reflection to other modules (p. 1191)
- Services it provides (p. 1196)
- Services it consumes (p. 1196)
In essence, a modular declaration specifies any modules its packages (and hence their classes) require to implement their functionality, and any packages that are provided for the benefit of other modules. Unless otherwise specified, other packages in the module are internal to the module—that is, they are not accessible to other modules.
The basic form of a module declaration is shown below. A module has a unique name. The body of the modular declaration can include module directives. The requires and exports directives are shown in the module declaration below. The modules required by a module for its internal implementation are specified using a requires directive, and the packages that other modules can utilize from it are specified using an exports directive. The latter is called an unqualified export as the exported package is available to any module that requires this module. (See §19.4, p. 1177, for an overview of all module directives.)
module
moduleName
{
// Body:
requires
moduleName
1
; // A requires directive.
…
requires
moduleName
n
;
exports
packageName
1
; // An exports directive.
…
exports
packageName
m
;
}
There can be zero or more such directives in such a module declaration. So a module declaration with no directive is valid, as it neither requires any modules (bar the java.base module) nor exports any of its packages.
The same directive cannot be duplicated. The directives can occur in any order, but conventionally they are grouped with requires directives preceding exports directives. In a module declaration, the word module is treated as a keyword only in the context of specifying the module name, and the words requires and exports are treated as keywords only in the context of specifying a module directive. They can be used as normal identifiers in all other contexts.
Only one module declaration can be specified in a file, which must be named module-info.java. No other declarations can be included in this file, and there can be no package statement either, but the import statement is allowed. This file also cannot be empty. As any other Java source code file, the module-info.java file with the module declaration is compiled and its bytecode is placed in a class file named module-info.class, called the module descriptor.
The graphical notation in Figure 19.3(a) and (b) shows two modules, client and seller, with their corresponding module declarations in Figure 19.3(c) and (d), respectively.
Figure 19.3 Modules and Module Declarations
- The name of the module: This is the unique name of the module to distinguish it from other modules.
In Figure 19.3(a) and (b), the names of the modules are client and seller, respectively. These module names are used in the respective module declaration in Figure 19.3(c) and (d).
- The required modules: These are the modules that a module requires for the types (i.e., classes and interfaces) in its packages.
In Figure 19.3(a) and (b), the client module requires the seller module and the seller module does not require any module, respectively. This is reflected in the respective module declarations in Figure 19.3(c) and (d): The module declaration for client has a requires directive specifying the seller module, but the module declaration for seller has no requires directive. The requires directive states that the specified module is required at compile time and runtime by the declared module.
The client module has a dependence on the seller module, called a module dependency, shown with a directed arrow from client module to seller module in Figure 19.3. Technically, the client module is said read the seller module. Often, we say module client depends on module seller, or module client requires module seller, or module seller is readable by module client. Although technically not correct, for the purpose of this discussion, they are all synonyms.
- The exported packages: These are packages that a module exports so other modules can utilize them for their own implementation. Exported packages define the public API of the declared module, where accessibility rules govern what types (and hence which members in these types) in an exported package are accessible to other modules (p. 1174).
In Figure 19.3(a) and (b), the client module does not export any packages and the seller module exports packages com.abc.seller and com.abc.factory. This is reflected in the respective module declarations: The module declaration for client has no exports directive, but the module declaration for seller has two exports directives that specify the exported packages.
Although the package com.abc.factory in module seller is exported, it does not imply that the package com.abc.factory.test is exported as well. This is analogous to the import statement, where packages must be imported individually.
- The internal packages: These are the packages that are internal to the module and therefore not accessible to other modules.
In Figure 19.3(a) and (b), the client module has an internal package com.abc.client and the seller module has an internal package com.abc.factory.test. However, there is no directive to specify an internal package in the module declaration. The question of how we implement a module and its packages in the file system is answered in §19.5, p. 1179.
Leave a Reply