static ·
‹ Previous Next ›
⏱ 5 min read Modified: 2026-09-26

Static Import in Java: import static Explained

You add import static java.util.Arrays.toString;, call toString(numbers) inside your class, and javac answers with error: method toString in class Object cannot be applied to given types. The import is there and Arrays.toString(int[]) exists, yet the compiler picks a completely different method. Understanding why takes two minutes, and it explains most of what you need to know about static import in Java.

Static import in Java is an import static declaration that lets you use static fields, static methods, and static member types of another class by their simple name, without the class prefix. For example, after import static java.lang.Math.PI; you can write PI instead of Math.PI. Static import was introduced in Java 5 and works only at compile time: it changes how names are resolved in the source code, not what the program does.

Accessing static members without an import

Normally you reach a static member through its class name. To call the static method cos() of Math and use its constant PI, you write Math twice:

public class WithoutStaticImportExample {
    public static void main(String[] args) {
        double value = Math.cos(Math.PI * 4);
        System.out.println(value); // 1.0
    }
}

In one line that is harmless. In a formula with a dozen Math. prefixes, the class name starts to bury the actual math. Static import removes that noise.

import static syntax

A static import looks like a regular import with the extra keyword static. After import static you write the fully qualified class name (package included), a dot, and then either a member name or an asterisk. The Java Language Specification calls these two forms single-static-import and static-import-on-demand.

Single-static-import: one name

package oop;

import static java.lang.Math.PI;
import static java.lang.Math.cos;

public class StaticImportExample {
    public static void main(String[] args) {
        double value = cos(PI * 4);
        System.out.println(value); // 1.0
    }
}

A single-static-import brings in every accessible static member with that name. import static java.lang.Math.max; makes all overloads available at once — max(int, int), max(long, long), max(double, double), and so on. You never list parameter types in an import; the compiler chooses the overload at the call site.

The same form works for static member types: import static java.util.Map.Entry; lets you write Entry<String, Integer> instead of Map.Entry<String, Integer>.

Static-import-on-demand: the wildcard *

The asterisk imports all accessible static members of one class:

import static java.lang.Math.*;

public class CircleArea {
    public static void main(String[] args) {
        double r = 2.5;
        double area = PI * pow(r, 2);
        System.out.println(round(area)); // 20
    }
}

Note that the wildcard applies to the members of a class, not to a package: import static java.lang.*; does not compile.

Where to put import static

import static declarations go in the same place as regular imports: after the package statement (if there is one) and before the first class declaration. The compiler accepts static and regular imports in any order, but most style guides, including Google Java Style, keep all static imports together in their own block, separate from the regular imports.

Under the hood

Static import is pure syntactic sugar. The compiler resolves cos(PI) to Math.cos(Math.PI), and the resulting bytecode is identical to the version with the class prefix. It has no effect on speed, memory, or class loading.

Static import examples

In real projects static import shows up in a few recurring situations.

System.out and utility constants

import static java.lang.System.out;
import static java.util.concurrent.TimeUnit.SECONDS;

public class TimeoutExample {
    public static void main(String[] args) {
        long millis = SECONDS.toMillis(30);
        out.println("Timeout: " + millis + " ms"); // Timeout: 30000 ms
    }
}

System.out is a static field of type PrintStream, so it can be imported like any other static field. println itself is an instance method and stays attached to out.

JUnit Assertions

The most common static import in Java code is in tests. assertEquals, assertTrue, and friends are almost always imported statically:

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.Test;

class CalculatorTest {
    @Test
    void addsNumbers() {
        assertEquals(5, 2 + 3);
        assertTrue(10 > 3);
    }
}

Stream API Collectors

import static java.util.stream.Collectors.counting;
import static java.util.stream.Collectors.groupingBy;

import java.util.List;
import java.util.Map;

public class GroupingExample {
    public static void main(String[] args) {
        List<String> words = List.of("java", "jvm", "stream", "static");
        Map<Character, Long> byFirstLetter = words.stream()
                .collect(groupingBy(w -> w.charAt(0), counting()));
        System.out.println(byFirstLetter); // {s=2, j=2}
    }
}

Enum constants

Enum constants are public static final fields of the enum type, so they can be statically imported too:

import static java.time.DayOfWeek.SATURDAY;
import static java.time.DayOfWeek.SUNDAY;

import java.time.DayOfWeek;
import java.time.LocalDate;

public class WeekendCheck {
    static boolean isWeekend(LocalDate date) {
        DayOfWeek day = date.getDayOfWeek();
        return day == SATURDAY || day == SUNDAY;
    }

    public static void main(String[] args) {
        System.out.println(isWeekend(LocalDate.of(2024, 6, 15))); // true
    }
}

Inside a switch on an enum you do not need a static import at all: case SATURDAY -> already works with the simple name.

Static import vs regular import

A regular import shortens type names; import static shortens member names. Side by side:

Characteristic import import static
What it imports Classes, interfaces, enums, records (types) Static fields, static methods, static member types
Example import java.util.List; import static java.lang.Math.PI;
Usage in code List.of(1, 2) instead of java.util.List.of(1, 2) PI instead of Math.PI
Wildcard form import java.util.*; — all types of a package import static java.lang.Math.*; — all static members of a class
Implicit import All types of java.lang None
Effect on bytecode None None

Name conflicts and shadowing

Same name from two classes

If two wildcard imports bring in members with the same name, nothing happens until you actually use that name. Then the compiler reports an ambiguity:

import static java.lang.Integer.*;
import static java.lang.Long.*;

public class AmbiguityExample {
    public static void main(String[] args) {
        System.out.println(MAX_VALUE); // compile error
    }
}
error: reference to MAX_VALUE is ambiguous
  both variable MAX_VALUE in Long and variable MAX_VALUE in Integer match

Fix it by importing the member you need by name (a single-static-import takes precedence over any on-demand import) or simply by writing Integer.MAX_VALUE.

Your own members win over imports

Names declared in the class itself, or inherited by it, shadow statically imported names. That is exactly what happens in the example from the top of this lesson. Every class inherits toString() from Object, so for the call toString(numbers) the compiler searches the class's own methods first, finds Object.toString() with no parameters, stops looking, and reports an error:

import static java.util.Arrays.toString;

public class ShadowingExample {
    public static void main(String[] args) {
        int[] numbers = {1, 2, 3};
        // System.out.println(toString(numbers)); // compile error
        System.out.println(java.util.Arrays.toString(numbers)); // [1, 2, 3]
    }
}
error: method toString in class Object cannot be applied to given types;
  required: no arguments
  found:    int[]
  reason: actual and formal argument lists differ in length

The same applies to equals and hashCode: statically importing Objects.equals or Arrays.hashCode is useless, because the methods inherited from Object always shadow them.

What you cannot import

  • Instance members. Non-static fields and methods cannot be imported with import static — they need an object.
  • Members of a class in the default package. A class without a package statement cannot be imported at all, neither with a regular nor with a static import.
  • Inaccessible members. private members of another class cannot be imported; an import never widens access rights.

When to use static import (and when not to)

Static import pays off when a member's name is clear on its own and is repeated often:

  • math-heavy code with Math (sqrt, pow, PI);
  • assertions and matchers in tests (JUnit, AssertJ, Mockito, Hamcrest);
  • collectors and factory-style helpers (toList(), groupingBy(), comparing());
  • frequently used constants and enum values.

Skip it when the class name carries meaning. A bare call of(1, 2) tells the reader nothing, while List.of(1, 2) tells them everything. Wildcard static imports from several classes in one file hurt readability too: whoever reads the code has to guess which class each name came from.

Style advice

The official Oracle guide recommends using static import "very sparingly" — only when you would otherwise repeat the class name many times. It was designed as the clean alternative to the "constant interface" antipattern: import the constants you need instead of implementing an interface just to inherit them.

Frequently Asked Questions

Which Java version introduced static import?

Java 5 (JDK 1.5), together with generics, enums, and varargs. The import static syntax has not changed since, so it works the same way in every modern Java version.

Does import static affect performance?

No. Imports exist only for the compiler: the bytecode always contains the fully qualified class name. A wildcard static import does not load extra classes and does not slow the program down either.

Can you statically import a non-static method?

No. import static works only with static fields, static methods, and static member types. An instance method needs an object to be called on, and no import can supply one.

Why don't I need to import Math, but cos and PI don't work without import static?

The java.lang package is imported automatically, but only at the type level: the name Math is available, its members are not. To write cos(PI) without a prefix you still need import static java.lang.Math.cos; and import static java.lang.Math.PI; (or import static java.lang.Math.*;).

Is a wildcard static import or importing each member better?

In production code, named imports are usually preferred: it is obvious where each name comes from, and ambiguities are less likely. A wildcard is acceptable for a single class whose members you use heavily, such as Math or an assertions class in tests.

Can you static import methods and constants from an interface?

Yes. Static methods of an interface (Java 8+) and interface constants are static members, so import static java.util.Comparator.comparing; works and lets you write list.sort(comparing(String::length));. Default and abstract interface methods are instance methods and cannot be imported.

Comments

Please log in or register to have a possibility to add comment.