Concepts / The Import Directive in Java

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.

  • Programming

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

Definition

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.

Key point

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.

import staticthe directive wordsjava.langpackage nameMathclass namesqrtstatic member name;ends the directive
In import static java.lang.Math.sqrt, which part of the path names the package, which names the class, and which names the member that becomes 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.

java
Notes on the code
  • 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.

java
Notes on the code
  • The star stands for every static member of Math.
  • Simple names such as sqrt and abs both become valid in the file.
FormShape of the directiveWhat it imports
Single-member formimport static package-name, then class-name, then static-member-name, then a semicolonOne named static member, such as sqrt
Wildcard formimport static package-name, then class-name, then a wildcard star, then a semicolonEvery 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.

java

What do you think happens?

Before reading the trace, predict what this program prints, and whether the sqrt(16) line compiles.

  • 4.0 then 3.0, each on its own line

  • A compile error on the sqrt(16) line

  • 4 then 3, each on its own line

Reveal answer
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.

Code walkthrough
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);
    }
}
  1. 1
    Line 1 the single-member static import brings the static member sqrt from java.lang.Math into view by simple name.
  2. 2
    Line 5 the simple name sqrt is looked up. The import on line 1 supplies Math.sqrt, so the call resolves and returns 4.0.
  3. 3
    Line 6 the compound name Math.sqrt(9) names the class directly, so it resolves without help from the import, and returns 3.0.
  4. 4
    Lines 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.
Output
4.0
3.0
sqrt(16)simple name at the callsiteLook for sqrtis there an import staticline for it?Math.sqrtsupplied by import staticjava.lang.Math.sqrtName not validno import supplies a classfor sqrtresolve the nameyesno
When the compiler reads the simple name sqrt at a call site, where does it look, and which import line makes the name resolve to Math.sqrt?
Worked example

Resolving 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?

  1. 1
    Identify the import lines

    The only import line in the file names the member sqrt of the class Math.

  2. 2
    Check sqrt(2)

    The simple name sqrt is supplied by the import line, so the call resolves to Math.sqrt and is valid.

  3. 3
    Check 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.

Result

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.

Before
double r = Math.sqrt(16);

The compound name Math.sqrt names its class at the call site.

After
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 comparisonOrdinary importStatic import
Example lineimport java.util.Scanner;import static java.lang.Math.sqrt;
What becomes simpleA class name, such as ScannerA static member name, such as sqrt
What the simple name refers toA classA static member of a class
How it is used in codeScanner input = new Scanner(System.in);double r = sqrt(16);

Ordinary import and static import compared

Key point

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 like
    double r = sqrt(16); in a file with no import static line
    Why it fails

    The 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 instead

    Add 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 fails

    A 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 instead

    Think 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 like
    import java.lang.Math.sqrt;
    Why it fails

    An 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 instead

    Write 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 like
    import static java.lang.Math;
    Why it fails

    The 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 instead

    Name 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

EASY

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.sqrt does 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.sqrt and System.out normally 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.