00:00

Static Import in Java – Using Static Members Without the Class Name

Last updated: 5 min read

Static import, added in Java 5, lets you use a class's static fields and methods without qualifying them with the class name. After import static java.lang.Math.*; you can write sqrt(x) and PI instead of Math.sqrt(x) and Math.PI.

Used carefully, static imports make code that relies heavily on a few utility methods or constants much easier to read, as in tests and stream pipelines. Overused, they make it unclear where a name comes from. This tutorial shows both sides.

1. Syntax

Syntax
import static package.ClassName.memberName;   // single static member
import static package.ClassName.*;            // all accessible static members (on demand)

Static imports go with the other imports, after the package statement. Importing a method name imports all its overloads.

2. Before and After

WithoutStaticImport.java
public class WithoutStaticImport {
    public static void main(String[] args) {
        double r = 2.5;
        double area = Math.PI * Math.pow(r, 2);
        double hyp = Math.sqrt(Math.pow(3, 2) + Math.pow(4, 2));
        System.out.printf("area = %.2f, hypotenuse = %.1f, max = %d%n", area, hyp, Math.max(7, 12));
    }
}
WithStaticImport.java
import static java.lang.Math.*;                 // all static members of Math
import static java.lang.System.out;             // a single static member

public class WithStaticImport {
    public static void main(String[] args) {
        double r = 2.5;
        double area = PI * pow(r, 2);
        double hyp = sqrt(pow(3, 2) + pow(4, 2));
        out.printf("area = %.2f, hypotenuse = %.1f, max = %d%n", area, hyp, max(7, 12));
    }
}
Output
area = 19.63, hypotenuse = 5.0, max = 12

Both programs produce the same output; the second reads more like the mathematical formula.

3. Where Static Imports Shine

Static imports are most valuable with APIs designed to be read fluently:

PracticalStaticImports.java
import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.counting;
import static java.time.temporal.ChronoUnit.DAYS;
import static java.util.concurrent.TimeUnit.MILLISECONDS;

import java.time.LocalDate;
import java.util.List;

public class PracticalStaticImports {
    record Book(String title, String category, int pages) { }

    public static void main(String[] args) throws InterruptedException {
        List<Book> books = List.of(new Book("Java Basics", "Java", 320),
                                   new Book("Kafka Guide", "Messaging", 280),
                                   new Book("Spring Boot", "Java", 410));

        // Fluent APIs read like prose with static imports
        System.out.println(books.stream().sorted(comparing(Book::pages)).map(Book::title).toList());
        System.out.println(books.stream().collect(groupingBy(Book::category, counting())));

        // Enum constants
        System.out.println(DAYS.between(LocalDate.of(2026, 1, 1), LocalDate.of(2026, 10, 11)) + " days");
        MILLISECONDS.sleep(10);
        System.out.println("slept 10 ms");
    }
}
Output
[Kafka Guide, Java Basics, Spring Boot]
{Java=2, Messaging=1}
283 days
slept 10 ms
  • Unit tests: import static org.junit.jupiter.api.Assertions.*; and AssertJ's assertThat.
  • Streams and comparators: Collectors.toList, groupingBy, Comparator.comparing.
  • Enum constants and units: ChronoUnit.DAYS, TimeUnit.SECONDS.
  • Mocking: Mockito's when, verify, mock.

4. Shadowing and Ambiguity

AmbiguityDemo.java
import static java.lang.Integer.MAX_VALUE;
import static java.lang.Integer.toHexString;

public class AmbiguityDemo {
    // A local member with the same name shadows the static import
    static String toHexString(int n) { return "local:" + n; }

    public static void main(String[] args) {
        System.out.println(MAX_VALUE);            // from Integer
        System.out.println(toHexString(255));     // the class's own method wins
        System.out.println(Integer.toHexString(255));   // qualify to use the imported one
        // import static java.lang.Long.MAX_VALUE; would make MAX_VALUE ambiguous when used
    }
}
Output
2147483647
local:255
ff
  • Members declared in the current class (or inherited) shadow statically imported members with the same name.
  • Single static imports take priority over on-demand (*) static imports.
  • If two on-demand imports provide the same name, using it is a compile error; qualify it with the class name.

5. Static Import vs Normal Import

Aspectimportimport static
ImportsTypes (classes, interfaces, enums, records)Static fields, static methods and static nested types
Lets you writeList instead of java.util.Listmax(a, b) instead of Math.max(a, b)
IntroducedJava 1.0Java 5

Neither affects performance or class loading; both are compile-time conveniences.

6. Best Practices

  • Use static imports sparingly, for members used many times and whose meaning is obvious without the class name.
  • Prefer importing specific members over * in production code; wildcards are common in tests.
  • Avoid static imports of members with generic names (of, valueOf, MAX_VALUE) that could come from many classes.
  • Do not use the "constant interface" anti-pattern (implementing an interface just to get its constants); static-import the constants instead.

7. Summary

  • import static brings static fields and methods into scope so they can be used without the class name.
  • Import a single member or all members with *.
  • Ideal for tests, stream collectors, comparators and enum constants.
  • Local members shadow static imports; conflicting on-demand imports are ambiguous.
  • Overuse hurts readability, so apply it selectively.

Related Tutorials