Table of Contents
Programs are organized as sets of packages. The members of a package (§7.1) are class and interface types, which are declared in compilation units of the package, and subpackages, which may contain compilation units and subpackages of their own.
Each package has its own set of names for types, which helps to prevent name conflicts. The naming structure for packages is hierarchical.
If a set of packages is sufficiently cohesive, then the packages may be grouped into a module. A module categorizes some or all of its packages as exported, which means their types may be accessed from code outside the module. If a package is not exported by a module, then only code inside the module may access its types. Furthermore, if code in a module wishes to access the packages exported by another module, then the first module must explicitly depend on the second module. Thus, a module controls how its packages use other modules (by specifying dependences) and controls how other modules use its packages (by specifying which of its packages are exported).
Modules and packages may be stored in a file system or in a database (§7.2). Modules and packages that are stored in a file system may have certain constraints on the organization of their compilation units to allow a simple implementation to find module and type declarations easily.
Code in a compilation unit automatically has access to all types declared in its package and also automatically imports all of thepublic types declared in the predefined packagejava.lang.
A top level type is accessible (§6.6) outside the package that declares it only if the type is declaredpublic. A top level type is accessible outside the module that declares it only if the type is declaredpublic and is a member of an exported package. A type that is declaredpublic but is not a member of an exported package is accessible only to code inside the module.
For small programs and casual development, a package can be unnamed (§7.4.2) or have a simple name, but if code is to be widely distributed, unique package names should be chosen using qualified names. This can prevent the conflicts that would otherwise occur if two development groups happened to pick the same package name and these packages were later to be used in a single program.
The members of a package are its subpackages and all the top level class types (§7.6,§8 (Classes)) and top level interface types (§9 (Interfaces)) declared in all the compilation units (§7.3) of the package.
For example, in the Java SE Platform API:
The packagejava has subpackagesawt,applet,io,lang,net, andutil, but no compilation units.
The packagejava.awt has a subpackage namedimage, as well as a number of compilation units containing declarations of class and interface types.
If the fully qualified name (§6.7) of a package isP, andQ is a subpackage ofP, thenP.Q is the fully qualified name of the subpackage, and furthermore denotes a package.
A package may not contain two members of the same name, or a compile-time error results.
Here are some examples:
Because the packagejava.awt has a subpackageimage, it cannot (and does not) contain a declaration of a class or interface type namedimage.
If there is a package namedmouse and a member typeButton in that package (which then might be referred to asmouse.Button), then there cannot be any package with the fully qualified namemouse.Button ormouse.Button.Click.
Ifcom.nighthacks.java.jag is the fully qualified name of a type, then there cannot be any package whose fully qualified name is eithercom.nighthacks.java.jag orcom.nighthacks.java.jag.scrabble.
It is however possible for members of different packages to have the same simple name. For example, it is possible to declare a package:
package vector;public class Vector { Object[] vec; }that has as a member apublic class namedVector, even though the packagejava.util also declares a class namedVector. These two class types are different, reflected by the fact that they have different fully qualified names (§6.7). The fully qualified name of this exampleVector isvector.Vector, whereasjava.util.Vector is the fully qualified name of theVector class included in the Java SE Platform. Because the packagevector contains a class namedVector, it cannot also have a subpackage namedVector.
The hierarchical naming structure for packages is intended to be convenient for organizing related packages in a conventional manner, but has no significance in itself other than the prohibition against a package having a subpackage with the same simple name as a top level type (§7.6) declared in that package.
For example, there is no special access relationship between a package namedoliver and another package namedoliver.twist, or between packages namedevelyn.wood andevelyn.waugh. That is, the code in a package namedoliver.twist has no better access to the types declared within packageoliver than code in any other package.
Each host system determines how modules, packages, and compilation units are created and stored.
Each host system determines which compilation units areobservable in a particular compilation (§7.3). Each host system also determines which observable compilation units areassociated with a module. The observability of compilation units associated with a module determines which modules are observable (§7.7.3) and which packages are visible within those modules (§7.4.3).
The host system is free to determine that a compilation unit which contains a module declaration is not, in fact, observable, and thus is not associated with the module declared therein. This enables a compiler to choose which directory on amodulesourcepath is "really" the embodiment of a given module. However, if the host system determines that a compilation unit which contains a module declarationis observable, then§7.4.3 mandates that the compilation unit must be associated with the module declared therein, and not with any other module.
The host system is free to determine that a compilation unit which contains a type declaration is (first) observable and (second) associated with an unnamed module or an automatic module - despite no declaration of an unnamed or automatic module existing in any compilation unit, observable or otherwise.
In simple implementations of the Java SE Platform, packages and compilation units may be stored in a local file system. Other implementations may store them using a distributed file system or some form of database.
If a host system stores packages and compilation units in a database, then the database must not impose the optional restrictions (§7.6) on compilation units permissible in file-based implementations.
For example, a system that uses a database to store packages may not enforce a maximum of one public class or interface per compilation unit.
Systems that use a database must, however, provide an option to convert a program to a form that obeys the restrictions, for purposes of export to file-based implementations.
As an extremely simple example of storing packages in a file system, all the packages and source and binary code in a project might be stored in a single directory and its subdirectories. Each immediate subdirectory of this directory would represent a top level package, that is, one whose fully qualified name consists of a single simple name. Each further level of subdirectory would represent a subpackage of the package represented by the containing directory, and so on.
The directory might contain the following immediate subdirectories:
comglsjagjavawnj
where directoryjava would contain the Java SE Platform packages; the directoriesjag,gls, andwnj might contain packages that three of the authors of this specification created for their personal use and to share with each other within this small group; and the directorycom would contain packages procured from companies that used the conventions described in§6.1 to generate unique names for their packages.
Continuing the example, the directoryjava would contain, among others, the following subdirectories:
appletawtiolangnetutil
corresponding to the packagesjava.applet,java.awt,java.io,java.lang,java.net, andjava.util that are defined as part of the Java SE Platform API.
Still continuing the example, if we were to look inside the directoryutil, we might see the following files:
BitSet.java Observable.javaBitSet.class Observable.classDate.java Observer.javaDate.class Observer.class...
where each of the.java files contains the source for a compilation unit (§7.3) that contains the definition of a class or interface whose binary compiled form is contained in the corresponding.class file.
Under this simple organization of packages, an implementation of the Java SE Platform would transform a package name into a pathname by concatenating the components of the package name, placing a file name separator (directory indicator) between adjacent components.
For example, if this simple organization were used on an operating system where the file name separator is/, the package name:
jag.scrabble.board
would be transformed into the directory name:
jag/scrabble/board
A package name component or class name might contain a character that cannot correctly appear in a host file system's ordinary directory name, such as a Unicode character on a system that allows only ASCII characters in file names. As a convention, the character can be escaped by using, say, the@ character followed by four hexadecimal digits giving the numeric value of the character, as in the\uxxxx escape (§3.3).
Under this convention, the package name:
children.activities.crafts.papierM\u00e2ch\u00e9
which can also be written using full Unicode as:
children.activities.crafts.papierMâché
might be mapped to the directory name:
children/activities/crafts/papierM@00e2ch@00e9
If the@ character is not a valid character in a file name for some given host file system, then some other character that is not valid in a identifier could be used instead.
CompilationUnit is the goal symbol (§2.1) for the syntactic grammar (§2.3) of Java programs. It is defined by the following production:
Anordinary compilation unit consists of three parts, each of which is optional:
Apackage declaration (§7.4), giving the fully qualified name (§6.7) of the package to which the compilation unit belongs.
A compilation unit that has nopackage declaration is part of an unnamed package (§7.4.2).
import declarations (§7.5) that allow types from other packages andstatic members of types to be referred to using their simple names.
Top level type declarations (§7.6) of class and interface types.
Amodular compilation unit consists of amodule declaration (§7.7), optionally preceded byimport declarations. Theimport declarations allow types from packages in this module and other modules, as well asstatic members of types, to be referred to using their simple names within themodule declaration.
Every compilation unit implicitly imports everypublic type name declared in the predefined packagejava.lang, as if the declarationimport java.lang.*; appeared at the beginning of each compilation unit immediately after anypackage declaration. As a result, the names of all those types are available as simple names in every compilation unit.
The host system determines which compilation units areobservable, except for the compilation units in the predefined packagejava and its subpackageslang andio, which are all always observable.
Each observable compilation unit may beassociated with a module, as follows:
The host system may determine that an observable ordinary compilation unit is associated with a module chosen by the host system, except for the ordinary compilation units in the predefined packagejava and its subpackageslang andio, which are all associated with thejava.base module.
The host system must determine that an observable modular compilation unit is associated with the module declared by the modular compilation unit.
The observability of a compilation unit influences the observability of its package (§7.4.3), while the association of an observable compilation unit with a module influences the observability of that module (§7.7.6).
When compiling the modular and ordinary compilation units associated with a moduleM, the host system must respect the dependences specified inM's declaration. Specifically, the host system must limit the ordinary compilation units that would otherwise be observable, to only those that arevisible toM. The ordinary compilation units that are visible toM are the observable ordinary compilation units associated with the modules that areread byM. The modules read byM are given by the result ofresolution, as described in thejava.lang.module package specification, withM as the only root module. The host system must perform resolution to determine the modules read byM; it is a compile-time error if resolution fails for any of the reasons described in thejava.lang.module package specification.
The readability relation is reflexive, soM reads itself, and thus all of the modular and ordinary compilation units associated withM are visible toM.
The modules read byM drive the packages that are uniquely visible toM (§7.4.3), which in turn drives both the top level packages in scope and the meaning of package names for code in the modular and ordinary compilation units associated withM (§6.3,§6.5.3,§6.5.5).
The rules above ensure that package/type names used in annotations in a modular compilation unit (in particular, annotations applied to the module declaration) are interpreted as if they appeared in an ordinary compilation unit associated with the module.
Types declared in different ordinary compilation units can refer to each other, circularly. A Java compiler must arrange to compile all such types at the same time.
Apackage declaration appears within an ordinary compilation unit to indicate the package to which the compilation unit belongs.
Apackage declaration in an ordinary compilation unit specifies the name (§6.2) of the package to which the compilation unit belongs.
The package name mentioned in apackage declaration must be the fully qualified name of the package (§6.7).
The scope and shadowing of a package declaration is specified in§6.3 and§6.4.
The rules for annotation modifiers on a package declaration are specified in§9.7.4 and§9.7.5.
At most one annotatedpackage declaration is permitted for a given package.
The manner in which this restriction is enforced must, of necessity, vary from implementation to implementation. The following scheme is strongly recommended for file-system-based implementations: The sole annotatedpackage declaration, if it exists, is placed in a source file calledpackage-info.java in the directory containing the source files for the package. This file does not contain the source for a class calledpackage-info; indeed it would be illegal for it to do so, aspackage-info is not a legal identifier. Typicallypackage-info.java contains only apackage declaration, preceded immediately by the annotations on the package. While the file could technically contain the source code for one or more classes with package access, it would be very bad form.
It is recommended thatpackage-info.java, if it is present, take the place ofpackage.html forjavadoc and other similar documentation generation systems. If this file is present, the documentation generation tool should look for the package documentation comment immediately preceding the (possibly annotated)package declaration inpackage-info.java. In this way,package-info.java becomes the sole repository for package-level annotations and documentation. If, in future, it becomes desirable to add any other package-level information, this file should prove a convenient home for this information.
An ordinary compilation unit that has nopackage declaration is part of anunnamed package.
Unnamed packages are provided by the Java SE Platform principally for convenience when developing small or temporary applications or when just beginning development.
An unnamed package cannot have subpackages, since the syntax of apackage declaration always includes a reference to a named top level package.
An implementation of the Java SE Platform must support at least one unnamed package. An implementation may support more than one unnamed package, but is not required to do so. Which ordinary compilation units are in each unnamed package is determined by the host system.
The host system must associate ordinary compilation units in an unnamed package with an unnamed module (§7.7.5), not a named module.
Example 7.4.2-1. Unnamed Package
The compilation unit:
class FirstCall { public static void main(String[] args) { System.out.println("Mr. Watson, come here. " + "I want you."); }}defines a very simple compilation unit as part of an unnamed package.
In implementations of the Java SE Platform that use a hierarchical file system for storing packages, one typical strategy is to associate an unnamed package with each directory; only one unnamed package is observable at a time, namely the one that is associated with the "current working directory". The precise meaning of "current working directory" depends on the host system.
A package isobservable if and only if at least one of the following is true:
An ordinary compilation unit containing a declaration of the package is observable (§7.3).
The packagesjava,java.lang, andjava.io are always observable.
One can conclude this from the rule above and from the rules of observable compilation units, as follows. The predefined packagejava.lang declares the classObject, so the compilation unit forObject is always observable (§7.3). Hence, thejava.lang package is observable, and thejava package also. Furthermore, sinceObject is observable, the array typeObject[] implicitly exists. Its superinterfacejava.io.Serializable (§10.1) also exists, hence thejava.io package is observable.
A package isvisible to a moduleM if and only if an ordinary compilation unit containing a declaration of the package is visible toM.
Package visibility is meant to imply that a package is "really" observable in some module on the system. It is not useful to think that package P is "technically" observable just because a subpackage P.Q is "technically" observable in some module. For example, suppose P.Q is "technically" observable in module M1 and P.R is "technically" observable in module M2; then, P is "technically" observable, but in M1 or M2 or both? During the compilwation of some module N that requires M1 only, it matters that P.Q is "really" observable, and it does not matter that P is "technically" observable.
A package isuniquely visible to a moduleM if and only if one of the following holds:
An ordinary compilation unit associated withM contains a declaration of the package, andM does not read any other module that exports the package toM.
No ordinary compilation unit associated withM contains a declaration of the package, andM reads exactly one other module that exports the package toM.
Animport declaration allows a named type or astatic member to be referred to by a simple name (§6.2) that consists of a single identifier.
Without the use of an appropriate import declaration, the only way to refer to a type declared in another package, or astatic member of another type, is to use a fully qualified name (§6.7).
A single-type-import declaration (§7.5.1) imports a single named type, by mentioning its canonical name (§6.7).
A type-import-on-demand declaration (§7.5.2) imports all the accessible types of a named type or named package as needed, by mentioning the canonical name of a type or package.
A single-static-import declaration (§7.5.3) imports all accessiblestatic members with a given name from a type, by giving its canonical name.
A static-import-on-demand declaration (§7.5.4) imports all accessiblestatic members of a named type as needed, by mentioning the canonical name of a type.
The scope and shadowing of a type or member imported by these declarations is specified in§6.3 and§6.4.
Animport declaration makes types or members available by their simple names only within the compilation unit that actually contains theimport declaration. The scope of the type(s) or member(s) introduced by animport declaration specifically does not include other compilation units in the same package, otherimport declarations in the current compilation unit, or apackage declaration in the current compilation unit (except for the annotations of apackage declaration).
Asingle-type-import declaration imports a single type by giving its canonical name, making it available under a simple name in the module, class, and interface declarations of the compilation unit in which the single-type-import declaration appears.
TheTypeName must be the canonical name of a class type, interface type, enum type, or annotation type (§6.7).
The type must be either a member of a named package, or a member of a type whose outermost lexically enclosing type declaration (§8.1.3) is a member of a named package, or a compile-time error occurs.
It is a compile-time error if the named type is not accessible (§6.6).
If two single-type-import declarations in the same compilation unit attempt to import types with the same simple name, then a compile-time error occurs, unless the two types are the same type, in which case the duplicate declaration is ignored.
If the type imported by the single-type-import declaration is declared in the compilation unit that contains theimport declaration, theimport declaration is ignored.
If a single-type-import declaration imports a type whose simple name isn, and the compilation unit also declares a top level type (§7.6) whose simple name isn, a compile-time error occurs.
If a compilation unit contains both a single-type-import declaration that imports a type whose simple name isn, and a single-static-import declaration (§7.5.3) that imports a type whose simple name isn, a compile-time error occurs, unless the two types are the same type, in which case the duplicate declaration is ignored.
Example 7.5.1-1. Single-Type-Import
import java.util.Vector;
causes the simple nameVector to be available within the class and interface declarations in a compilation unit. Thus, the simple nameVector refers to the type declarationVector in the packagejava.util in all places where it is not shadowed (§6.4.1) or obscured (§6.4.2) by a declaration of a field, parameter, local variable, or nested type declaration with the same name.
Note that the actual declaration ofjava.util.Vector is generic (§8.1.2). Once imported, the nameVector can be used without qualification in a parameterized type such asVector<String>, or as the raw typeVector. A related limitation of theimport declaration is that a nested type declared inside a generic type declaration can be imported, but its outer type is always erased.
Example 7.5.1-2. Duplicate Type Declarations
This program:
import java.util.Vector;class Vector { Object[] vec; }causes a compile-time error because of the duplicate declaration ofVector, as does:
import java.util.Vector;import myVector.Vector;
wheremyVector is a package containing the compilation unit:
package myVector;public class Vector { Object[] vec; }Example 7.5.1-3. No Import of a Subpackage
Note that animport declaration cannot import a subpackage, only a type.
For example, it does not work to try to importjava.util and then use the nameutil.Random to refer to the typejava.util.Random:
import java.util;class Test { util.Random generator; } // incorrect: compile-time errorExample 7.5.1-4. Importing a Type Name that is also a Package Name
Package names and type names are usually different under the naming conventions described in§6.1. Nevertheless, in a contrived example where there is an unconventionally-named packageVector, which declares a public class whose name isMosquito:
package Vector;public class Mosquito { int capacity; }and then the compilation unit:
package strange;import java.util.Vector;import Vector.Mosquito;class Test { public static void main(String[] args) { System.out.println(new Vector().getClass()); System.out.println(new Mosquito().getClass()); }}the single-type-import declaration importing classVector from packagejava.util does not prevent the package nameVector from appearing and being correctly recognized in subsequentimport declarations. The example compiles and produces the output:
class java.util.Vectorclass Vector.Mosquito
Atype-import-on-demand declaration allows all accessible types of a named package or type to be imported as needed.
ThePackageOrTypeName must be the canonical name (§6.7) of a package, a class type, an interface type, an enum type, or an annotation type.
If thePackageOrTypeName denotes a type (§6.5.4), then the type must be either a member of a named package, or a member of a type whose outermost lexically enclosing type declaration (§8.1.3) is a member of a named package, or a compile-time error occurs.
It is a compile-time error if the named package is not uniquely visible to the current module (§7.4.3), or if the named type is not accessible (§6.6).
It is not a compile-time error to name eitherjava.lang or the named package of the current compilation unit in a type-import-on-demand declaration. The type-import-on-demand declaration is ignored in such cases.
Two or more type-import-on-demand declarations in the same compilation unit may name the same type or package. All but one of these declarations are considered redundant; the effect is as if that type was imported only once.
If a compilation unit contains both a type-import-on-demand declaration and a static-import-on-demand declaration (§7.5.4) that name the same type, the effect is as if thestatic member types of that type (§8.5,§9.5) were imported only once.
Example 7.5.2-1. Type-Import-on-Demand
import java.util.*;
causes the simple names of allpublic types declared in the packagejava.util to be available within the class and interface declarations of the compilation unit. Thus, the simple nameVector refers to the typeVector in the packagejava.util in all places in the compilation unit where that type declaration is not shadowed (§6.4.1) or obscured (§6.4.2).
The declaration might be shadowed by a single-type-import declaration of a type whose simple name isVector; by a type namedVector and declared in the package to which the compilation unit belongs; or any nested classes or interfaces.
The declaration might be obscured by a declaration of a field, parameter, or local variable namedVector.
(It would be unusual for any of these conditions to occur.)
Asingle-static-import declaration imports all accessiblestatic members with a given simple name from a type. This makes thesestatic members available under their simple name in the module, class, and interface declarations of the compilation unit in which the single-static-import declaration appears.
TheTypeName must be the canonical name (§6.7) of a class type, interface type, enum type, or annotation type.
The type must be either a member of a named package, or a member of a type whose outermost lexically enclosing type declaration (§8.1.3) is a member of a named package, or a compile-time error occurs.
It is a compile-time error if the named type is not accessible (§6.6).
TheIdentifier must name at least onestatic member of the named type. It is a compile-time error if there is nostatic member of that name, or if all of the named members are not accessible.
It is permissible for one single-static-import declaration to import several fields or types with the same name, or several methods with the same name and signature. This occurs when the named type inherits multiple fields, member types, or methods, all with the same name, from its own supertypes.
If two single-static-import declarations in the same compilation unit attempt to import types with the same simple name, then a compile-time error occurs, unless the two types are the same type, in which case the duplicate declaration is ignored.
If a single-static-import declaration imports a type whose simple name isn, and the compilation unit also declares a top level type (§7.6) whose simple name isn, a compile-time error occurs.
If a compilation unit contains both a single-static-import declaration that imports a type whose simple name isn, and a single-type-import declaration (§7.5.1) that imports a type whose simple name isn, a compile-time error occurs, unless the two types are the same type, in which case the duplicate declaration is ignored.
Astatic-import-on-demand declaration allows all accessiblestatic members of a named type to be imported as needed.
TheTypeName must be the canonical name (§6.7) of a class type, interface type, enum type, or annotation type.
The type must be either a member of a named package, or a member of a type whose outermost lexically enclosing type declaration (§8.1.3) is a member of a named package, or a compile-time error occurs.
It is a compile-time error if the named type is not accessible (§6.6).
Two or more static-import-on-demand declarations in the same compilation unit may name the same type; the effect is as if there was exactly one such declaration.
Two or more static-import-on-demand declarations in the same compilation unit may name the same member; the effect is as if the member was imported exactly once.
It is permissible for one static-import-on-demand declaration to import several fields or types with the same name, or several methods with the same name and signature. This occurs when the named type inherits multiple fields, member types, or methods, all with the same name, from its own supertypes.
If a compilation unit contains both a static-import-on-demand declaration and a type-import-on-demand declaration (§7.5.2) that name the same type, the effect is as if thestatic member types of that type (§8.5,§9.5) were imported only once.
Atop level type declaration declares a top level class type (§8 (Classes)) or a top level interface type (§9 (Interfaces)).
Extra ";" tokens appearing at the level of type declarations in a compilation unit have no effect on the meaning of the compilation unit. Stray semicolons are permitted in the Java programming language solely as a concession to C++ programmers who are used to placing ";" after a class declaration. They should not be used in new Java code.
In the absence of an access modifier, a top level type has package access: it is accessible only within ordinary compilation units of the package in which it is declared (§6.6.1). A type may be declaredpublic to grant access to the type from code in other packages of the same module, and potentially from code in packages of other modules.
It is a compile-time error if a top level type declaration contains any one of the following access modifiers:protected,private, orstatic.
It is a compile-time error if the name of a top level type appears as the name of any other top level class or interface type declared in the same package.
The scope and shadowing of a top level type is specified in§6.3 and§6.4.
The fully qualified name of a top level type is specified in§6.7.
Example 7.6-1. Conflicting Top Level Type Declarations
package test;import java.util.Vector;class Point { int x, y;}interface Point { // compile-time error #1 int getR(); int getTheta();}class Vector { Point[] pts; } // compile-time error #2Here, the first compile-time error is caused by the duplicate declaration of the namePoint as both a class and an interface in the same package. A second compile-time error is the attempt to declare the nameVector both by a class type declaration and by a single-type-import declaration.
Note, however, that it is not an error for the name of a class to also name a type that otherwise might be imported by a type-import-on-demand declaration (§7.5.2) in the compilation unit (§7.3) containing the class declaration. Thus, in this program:
package test;import java.util.*;class Vector {} // not a compile-time errorthe declaration of the classVector is permitted even though there is also a classjava.util.Vector. Within this compilation unit, the simple nameVector refers to the classtest.Vector, not tojava.util.Vector (which can still be referred to by code within the compilation unit, but only by its fully qualified name).
Example 7.6-2. Scope of Top Level Types
package points;class Point { int x, y; // coordinates PointColor color; // color of this point Point next; // next point with this color static int nPoints;}class PointColor { Point first; // first point with this color PointColor(int color) { this.color = color; } private int color; // color components}This program defines two classes that use each other in the declarations of their class members. Because the class typesPoint andPointColor have all the type declarations in packagepoints, including all those in the current compilation unit, as their scope, this program compiles correctly. That is, forward reference is not a problem.
Example 7.6-3. Fully Qualified Names
class Point { int x, y; }In this code, the classPoint is declared in a compilation unit with nopackage declaration, and thusPoint is its fully qualified name, whereas in the code:
package vista;class Point { int x, y; }the fully qualified name of the classPoint isvista.Point. (The package namevista is suitable for local or personal use; if the package were intended to be widely distributed, it would be better to give it a unique package name (§6.1).)
An implementation of the Java SE Platform must keep track of types within packages by the combination of their enclosing module names and their binary names (§13.1). Multiple ways of naming a type must be expanded to binary names to make sure that such names are understood as referring to the same type.
For example, if a compilation unit contains the single-type-import declaration (§7.5.1):
import java.util.Vector;
then within that compilation unit, the simple nameVector and the fully qualified namejava.util.Vector refer to the same type.
If and only if packages are stored in a file system (§7.2), the host system may choose to enforce the restriction that it is a compile-time error if a type is not found in a file under a name composed of the type name plus an extension (such as.java or.jav) if either of the following is true:
This restriction implies that there must be at most one such type per compilation unit. This restriction makes it easy for a Java compiler to find a named class within a package. In practice, many programmers choose to put each class or interface type in its own compilation unit, whether or not it ispublic or is referred to by code in other compilation units.
For example, the source code for apublic typewet.sprocket.Toad would be found in a fileToad.java in the directorywet/sprocket, and the corresponding object code would be found in the fileToad.class in the same directory.
A module declaration specifies a new named module. A named module specifiesdependences on other modules to define the universe of classes and interfaces available to its own code; and specifies which of its packages areexported oropened in order to populate the universe of classes and interfaces available to other modules which specify a dependence on it.
A "dependence" is what is expressed by arequires directive, independent of whether a module exists with the name specified by the directive. A "dependency" is the observable module enumerated by resolution (as described in thejava.lang.module package specification) for a givenrequires directive. Generally, the rules of the Java programming language are more interested in dependences than dependencies.
A module declaration introduces a module name that can be used in other module declarations to express relationships between modules. A module name consists of one or more Java identifiers (§3.8) separated by "." tokens.
There are two kinds of modules:normal modules andopen modules. The kind of a module determines the nature of access to the module's types, and the members of those types, for code outside the module.
A normal module, without theopen modifier, grants access at compile time and run time to types in only those packages which are explicitly exported.
An open module, with theopen modifier, grants access at compile time to types in only those packages which are explicitly exported, but grants access at run time to types in all its packages, as if all packages had been exported.
For code outside a module (whether the module is normal or open), the access granted at compile time or run time to types in the module's exported packages is specifically to thepublic andprotected types in those packages, and thepublic andprotected members of those types (§6.6). No access is granted at compile time or run time to types, or their members, in packages which are not exported. Code inside the module may accesspublic andprotected types, and thepublic andprotected members of those types, in all packages in the module at both compile time and run time.
Distinct from access at compile time and access at run time, the Java SE Platform providesreflective access via the Core Reflection API (§1.4). A normal module grants reflective access to types in only those packages which are explicitly exported or explicitly opened (or both). An open module grants reflective access to types in all its packages, as if all packages had been opened.
For code outside a normal module, the reflective access granted to types in the module's exported (and not opened) packages is specifically to thepublic andprotected types in those packages, and thepublic andprotected members of those types. The reflective access granted to types in the module's opened packages (whether exported or not) is to all types in those packages, and all members of those types. No reflective access is granted to types, or their members, in packages which are not exported or opened. Code inside the module enjoys reflective access to all types, and all their members, in all packages in the module.
For code outside an open module, the reflective access granted to types in the module's opened packages (that is, all packages in the module) is to all types in those packages, and all members of those types. Code inside the module enjoys reflective access to all types, and all their members, in all packages in the module.
Thedirectives of a module declaration specify the module's dependences on other modules (viarequires,§7.7.1), the packages it makes available to other modules (viaexports andopens,§7.7.2), the services it consumes (viauses,§7.7.3), and the services it provides (viaprovides,§7.7.4).
requires {RequiresModifier}ModuleName;exportsPackageName [toModuleName {,ModuleName}];opensPackageName [toModuleName {,ModuleName}];usesTypeName;providesTypeNamewithTypeName {,TypeName}; If and only if packages are stored in a file system (§7.2), the host system may choose to enforce the restriction that it is a compile-time error if a module declaration is not found in a file under a name composed ofmodule-info plus an extension (such as.java or.jav).
To aid comprehension, it is customary, though not required, for a module declaration to group its directives, so that therequires directives which pertain to modules are visually distinct from theexports andopens directives which pertain to packages, and from theuses andprovides directives which pertain to services. For example:
module com.example.foo { requires com.example.foo.http; requires java.logging; requires transitive com.example.foo.network; exports com.example.foo.bar; exports com.example.foo.internal to com.example.foo.probe; opens com.example.foo.quux; opens com.example.foo.internal to com.example.foo.network, com.example.foo.probe; uses com.example.foo.spi.Intf; provides com.example.foo.spi.Intf with com.example.foo.Impl;}Theopens directives can be avoided if the module is open:
open module com.example.foo { requires com.example.foo.http; requires java.logging; requires transitive com.example.foo.network; exports com.example.foo.bar; exports com.example.foo.internal to com.example.foo.probe; uses com.example.foo.spi.Intf; provides com.example.foo.spi.Intf with com.example.foo.Impl;}Development tools for the Java programming language are encouraged to highlightrequirestransitive directives and unqualifiedexports directives, as these form the primary API of a module.
Therequires directive specifies the name of a module on which the current module has a dependence.
Arequires directive must not appear in the declaration of thejava.base module, or a compile-time error occurs, because it is the primordial module and has no dependences (§8.1.4).
If the declaration of a module does not express a dependence on thejava.base module, and the module is not itselfjava.base, then the module has an implicitly declared dependence on thejava.base module.
Therequires keyword may be followed by the modifiertransitive. This causes any module whichrequires the current module to have an implicitly declared dependence on the module specified by therequirestransitive directive.
Therequires keyword may be followed by the modifierstatic. This specifies that the dependence, while mandatory at compile time, is optional at run time.
If the declaration of a module expresses a dependence on thejava.base module, and the module is not itselfjava.base, then it is a compile-time error if a modifier appears after therequires keyword.
It is a compile-time error if more than onerequires directive in a module declaration specifies the same module name.
It is a compile-time error if resolution, as described in thejava.lang.module package specification, with the current module as the only root module, fails for any of the reasons described in thejava.lang.module package specification.
For example, if arequires directive specifies a module that is not observable, or if the current module directly or indirectly expresses a dependence on itself.
If resolution succeeds, then its result specifies the modules that are read by the current module. The modules read by the current module determine which ordinary compilation units are visible to the current module (§7.3). The types declared in those ordinary compilation units (andonly those ordinary compilation units) may be accessible to code in the current module (§6.6).
The Java SE Platform distinguishes between named modules that are explicitly declared (that is, with a module declaration) and named modules that are implicitly declared (that is, automatic modules). However, the Java programming language does not surface the distinction:requires directives refer to named modules without regard for whether they are explicitly declared or implicitly declared.
While automatic modules are convenient for migration, they are unreliable in the sense that their names and exported packages may change when their authors convert them to explicitly declared modules. A Java compiler is encouraged to issue a warning if arequires directive refers to an automatic module. An especially strong warning is recommended if thetransitive modifier appears in the directive.
Example 7.1.1-1. Resolution ofrequirestransitive directives
Suppose there are four module declarations as follows:
module m.A { requires m.B;}module m.B { requires transitive m.C;}module m.C { requires transitive m.D;}module m.D { exports p;}where the packagep exported bym.D is declared as follows:
package p;public class Point {}and where a packageclient in modulem.A refers to thepublic typePoint in the exported packagep:
package client;import p.Point;public class Test { public static void main(String[] args) { System.out.println(new Point()); }}The modules may be compiled as follows, assuming that the current directory has one subdirectory per module, named after the module it contains:
javac --module-source-path . -d . --module m.Djavac --module-source-path . -d . --module m.Cjavac --module-source-path . -d . --module m.Bjavac --module-source-path . -d . --module m.A
The programclient.Test may be run as follows:
java --module-path . --module m.A/client.Test
The reference from code inm.A to the exportedpublic typePoint inm.D is legal becausem.A readsm.D, andm.D exports the package containingPoint. Resolution determines thatm.A readsm.D as follows:
m.Arequiresm.B and therefore readsm.B.
Sincem.A readsm.B, and sincem.Brequirestransitivem.C, resolution determines thatm.A readsm.C.
Then, sincem.A readsm.C, and sincem.Crequirestransitivem.D, resolution determines thatm.A readsm.D.
In effect, a module may read another module through multiple levels of dependence, in order to support arbitrary amounts of refactoring. Once a module is released for someone to reuse (viarequires), the module's author has committed to its name and API but is free to refactor its content into other modules which the original module reuses (viarequirestransitive) for the benefit of consumers. In the example above, packagep may have been exported originally bym.B (thus,m.Arequiresm.B) but refactoring has caused some ofm.B's content to move intom.C andm.D. By using a chain ofrequirestransitive directives, the family ofm.B,m.C, andm.D can preserve access to packagep for code inm.A without forcing any changes to therequires directives ofm.A. Note that packagep inm.D is not "re-exported" bym.C andm.B; rather,m.A is made to readm.D directly.
Theexports directive specifies the name of a package to be exported by the current module. For code in other modules, this grants access at compile time and run time to thepublic andprotected types in the package, and thepublic andprotected members of those types (§6.6). It also grants reflective access to those types and members for code in other modules.
Theopens directive specifies the name of a package to be opened by the current module. For code in other modules, this grants access at run time, but not compile time, to thepublic andprotected types in the package, and thepublic andprotected members of those types. It also grants reflective access to all types in the package, and all their members, for code in other modules.
It is a compile-time error if the package specified byexports is not declared by a compilation unit associated with the current module (§7.3).
It is permitted foropens to specify a package which is not declared by a compilation unit associated with the current module. (If the package should happen to be declared by an observable compilation unit associated with another module, theopens directive has no effect on that other module.)
It is a compile-time error if more than oneexports directive in a module declaration specifies the same package name.
It is a compile-time error if more than oneopens directive in a module declaration specifies the same package name.
It is a compile-time error if anopens directive appears in the declaration of an open module.
If anexports oropens directive has ato clause, then the directive isqualified; otherwise, it isunqualified. For a qualified directive, thepublic andprotected types in the package, and theirpublic andprotected members, are accessible solely to code in the modules specified in theto clause. The modules specified in theto clause are referred to asfriends of the current module. For an unqualified directive, these types and their members are accessible to code in any module.
It is permitted for theto clause of anexports oropens directive to specify a module which is not observable (§7.7.6).
It is a compile-time error if theto clause of a givenexports directive specifies the same module name more than once.
It is a compile-time error if theto clause of a givenopens directive specifies the same module name more than once.
Theuses directive specifies aservice for which the current module may discover providers viajava.util.ServiceLoader.
The service must be a class type, an interface type, or an annotation type. It is a compile-time error if auses directive specifies an enum type (§8.9) as the service.
The service may be declared in the current module or in another module. If the service is not declared in the current module, then the service must be accessible to code in the current module (§6.6), or a compile-time error occurs.
It is a compile-time error if more than oneuses directive in a module declaration specifies the same service.
Theprovides directive specifies a service for which thewith clause specifies one or moreservice providers tojava.util.ServiceLoader.
The service must be a class type, an interface type, or an annotation type. It is a compile-time error if aprovides directive specifies an enum type (§8.9) as the service.
The service may be declared in the current module or in another module. If the service is not declared in the current module, then the service must be accessible to code in the current module (§6.6), or a compile-time error occurs.
Every service provider must be a class type or an interface type, that ispublic, and that is top level or nestedstatic, or a compile-time error occurs.
Every service provider must be declared in the current module, or a compile-time error occurs.
If a service provider explicitly declares apublic constructor with no formal parameters, or implicitly declares apublic default constructor (§8.8.9), then that constructor is called theprovider constructor.
If a service provider explicitly declares apublicstatic method calledprovider with no formal parameters, then that method is called theprovider method.
If a service provider has a provider method, then its return type must i) either be declared in the current module, or be declared in another module and be accessible to code in the current module; and ii) be a subtype of the service specified in theprovides directive; or a compile-time error occurs.
While a service provider that is specified by aprovides directive must be declared in the current module, its provider method may have a return type that is declared inanother module. Also, note that when a service provider declares a provider method, the service provider itself need not be a subtype of the service.
If a service provider does not have a provider method, then that service provider must have a provider constructor and must be a subtype of the service specified in theprovides directive, or a compile-time error occurs.
It is a compile-time error if more than oneprovides directive in a module declaration specifies the same service.
It is a compile-time error if thewith clause of a givenprovides directive specifies the same service provider more than once.
An observable ordinary compilation unit that the host system does not associate with a named module (§7.3) is associated with anunnamed module.
Unnamed modules are provided by the Java SE Platform in recognition of the fact that programs developed prior to Java SE 9 could not declare named modules. In addition, the reasons for the Java SE Platform providing unnamed packages (§7.4.2) are largely applicable to unnamed modules.
An implementation of the Java SE Platform must support at least one unnamed module. An implementation may support more than one unnamed module, but is not required to do so. Which ordinary compilation units are associated with each unnamed module is determined by the host system.
The host system may associate ordinary compilation units in a named package with an unnamed module.
The rules for unnamed modules are designed to maximize their interoperation with named modules, as follows:
An unnamed module reads every observable module (§7.7.6).
By virtue of the fact that an ordinary compilation unit associated with an unnamed module is observable, the associated unnamed module is observable. Thus, if the implementation of the Java SE Platform supports more than one unnamed module, every unnamed module is observable; and each unnamed module reads every unnamed module including itself.
However, it is important to realize that the ordinary compilation units of an unnamed module are nevervisible to a named module (§7.3) because norequires directive can arrange for a named module to read an unnamed module. The Core Reflection API of the Java SE Platform may be used to arrange for a named module to read an unnamed module at run time.
An unnamed module exports every package whose ordinary compilation units are associated with that unnamed module.
An unnamed module opens every package whose ordinary compilation units are associated with that unnamed module.
A module is observable if at least one of the following is true:
A modular compilation unit containing the declaration of the module is observable (§7.3).
An ordinary compilation unit associated with the module is observable.