The Import Directive in Java
A static import lets a static member of a class be referred to by its simple name, which removes the need for compound names such as Math.sqrt.
Why Long Names Pile Up
Earlier in the import material, a class such as java.util.Scanner could be written with its simple name, Scanner, once an import directive brought it into view. Static members follow a different rule. A static member variable such as System.out, or a static method such as Math.sqrt, still has to be written with a compound name that begins with the class name.
The consequence is repetition. Every call to the square root function carries the prefix Math, and every print statement carries the prefix System.out. A program that computes several square roots and prints each one ends up repeating Math and System.out many times. The import directive can be extended to remove that repetition, and that extension is the static import.
What a Static Import Actually Does
A static import lets a static member of a class be referred to by its simple name. This removes the need for a compound name such as Math.sqrt at each use.
A static import does not create a new method and does not copy one into the file. The member stays where it was defined, inside its class. What changes is only how the name is written at the point of use. The import line tells the compiler that a particular simple name, when it appears in this file, should be read as a static member of a named class, and the import line is what supplies that class.
A static import changes the spelling at the point of use. It does not change where the member lives, and it does not duplicate the member.
The Two Forms of the Directive
Both forms of the static import directive begin with the words import static, followed by a package name and a class name. What comes after the class name decides how much is imported. The single-member form names one static member. The wildcard form makes every static member of the class available by simple name.
In the single-member form, the path ends in one member name, so exactly that member is imported. The line below imports only the sqrt method from the Math class in the java.lang package.
- Only the static member sqrt becomes available by its simple name.
- Other static members of Math, such as abs, are not brought into scope by this line.
In the wildcard form, the member position is filled by a star instead of a name. Every static member of the class then becomes available by simple name. The line below does this for the Math class.
- The star stands for every static member of Math.
- Simple names such as sqrt and abs both become valid in the file.
| Form | Shape of the directive | What it imports |
|---|---|---|
| Single-member form | import static package-name, then class-name, then static-member-name, then a semicolon | One named static member, such as sqrt |
| Wildcard form | import static package-name, then class-name, then a wildcard star, then a semicolon | Every static member of the class, by simple name |
The two forms of the static import directive
Tracing a Program With a Static Import
The program below uses the static import for sqrt on one line and the compound form Math.sqrt on another, so both naming styles appear side by side. Read the first line before the rest of the program. That line decides whether the simple name sqrt is valid anywhere else in the file.
What do you think happens?
Before reading the trace, predict what this program prints, and whether the sqrt(16) line compiles.
Reveal answer
4.0 then 3.0, each on its own line
The import static line makes the simple name sqrt refer to Math.sqrt, so sqrt(16) is valid and returns 4.0. The compound call Math.sqrt(9) is valid as well and returns 3.0. Math.sqrt returns a double, so println shows the values with a decimal point.
import static java.lang.Math.sqrt;
public class SquareRoots {
public static void main(String[] args) {
double a = sqrt(16);
double b = Math.sqrt(9);
System.out.println(a);
System.out.println(b);
}
}- 1Line 1 the single-member static import brings the static member sqrt from
java.lang.Mathinto view by simple name. - 2Line 5 the simple name sqrt is looked up. The import on line 1 supplies
Math.sqrt, so the call resolves and returns 4.0. - 3Line 6 the compound name
Math.sqrt(9)names the class directly, so it resolves without help from the import, and returns 3.0. - 4Lines 7 and 8: each value is printed, one per line.
- Line 1 is the static import that makes the simple name sqrt valid in this file.
- Line 6 uses the compound name, which does not depend on the import line.
4.0
3.0Resolving Two Calls in One File
The file contains only the line import static java.lang.Math.sqrt; and then calls sqrt(2) and abs(-3). Which calls are valid, and which line is responsible for each simple name?
- 1Identify the import lines
The only import line in the file names the member sqrt of the class Math.
- 2Check sqrt(2)
The simple name sqrt is supplied by the import line, so the call resolves to
Math.sqrtand is valid. - 3Check abs(-3)
No import line supplies the simple name abs. The single-member form brings in only sqrt, so abs is not valid as a bare name here.
sqrt(2) is valid because of the import line. abs(-3) is not valid as written, because nothing in the file makes the simple name abs refer to Math.abs.
Compound Names Versus Simple Names
The next comparison shows what changes in the code when a static import is added. The square root call is written first with the compound name, and then with the simple name supplied by the import line. The method being called is the same in both versions. Only the spelling at the call site and the import line that supports it are different.
double r = Math.sqrt(16);The compound name Math.sqrt names its class at the call site.
import static java.lang.Math.sqrt;
double r = sqrt(16);The simple name sqrt is valid because the import line names its class.
Static Import Versus Ordinary Import
An ordinary import and a static import look alike on the page, but they answer different questions. The ordinary import answers the question of how a class name can be written simply. The static import answers the question of how a static member name can be written simply. The table below compares the two on these points.
| Point of comparison | Ordinary import | Static import |
|---|---|---|
| Example line | import java.util.Scanner; | import static java.lang.Math.sqrt; |
| What becomes simple | A class name, such as Scanner | A static member name, such as sqrt |
| What the simple name refers to | A class | A static member of a class |
| How it is used in code | Scanner input = new Scanner(System.in); | double r = sqrt(16); |
Ordinary import and static import compared
Ask what the name after the import line names. If it names a class, the directive is an ordinary import. If it names a static member of a class, the directive is a static import with the import static words.
Mistakes Beginners Make With Static Imports
Common mistake Using a simple name for a static member when no import supplies it
What it looks likedouble r = sqrt(16); in a file with no import static lineWhy it failsThe simple name sqrt is valid only where an import line supplies the class. Without one, the name is not connected to
Math.sqrt.Do this insteadAdd import static java.lang.Math.sqrt; at the top of the file, or write the compound name Math.sqrt(16).
Common mistake Thinking the static import copies the method into the file
Why it failsA static import does not create or copy a method. The member stays inside its class, and the import only changes how the name is written at the point of use.
Do this insteadThink of the import line as a rule for reading a simple name, not as a definition of a new method.
Common mistake Writing a static member in an ordinary import
What it looks likeimport java.lang.Math.sqrt;Why it failsAn ordinary import makes a class name simple. The name sqrt is a static member, not a class, so the directive needs the static words.
Do this insteadWrite import static java.lang.Math.sqrt; so the directive names a static member.
Common mistake Leaving out the member name in the single-member form
What it looks likeimport static java.lang.Math;Why it failsThe single-member form names one static member after the class name. Stopping at the class name does not say which member is imported.
Do this insteadName the member, as in import static java.lang.Math.sqrt;, or use the wildcard star if every static member is wanted.
Checking Your Reading of an Import Line
A file's only import line is import static java.lang.Math.sqrt;. The file then contains the calls sqrt(2), Math.sqrt(2), and abs(-3). Which of the three calls are valid, and which import line makes each simple name valid?
Hints
- Start by identifying which simple name the import line makes valid.
- A compound name such as
Math.sqrtdoes not depend on the import line, because it names its class directly. - Ask whether any line in the file supplies the simple name abs.
Key Takeaways
- Static members such as
Math.sqrtandSystem.outnormally need compound names that begin with the class name, which is why repetition builds up in code. - A static import lets a static member be referred to by its simple name. The single-member form imports one named member, and the wildcard form imports every static member of the class.
- A static import does not create or copy a method. It changes only how the name is written at the point of use, and the import line is what makes the simple name valid.
- An ordinary import makes a class name simple, while a static import makes a static member name simple. Confusing the two produces mistakes such as importing a member without the static words.