skip to content

What is a static import in Java, and how does it differ from a regular import?

level: juniorimportance: should knowfreq 55%

answer

  1. import vs import static
  2. member not type
  3. Math.max -> max
  4. compile-time sugar, same bytecode
  5. Java 5

basics

~20 s

A regular import lets you use a class by its simple name. A static import lets you use a class's static members (fields or methods) by their simple name, without writing the class name first, e.g. just max(a,b) instead of Math.max(a,b).

solid answer

~40 s

A normal import (import java.util.List;) brings a type into scope so you can write List instead of java.util.List. A static import (import static java.lang.Math.max;) instead brings a specific static member of a type into scope, so you can reference that static field or method unqualified. After importing Math.max statically you write max(a, b) rather than Math.max(a, b); after a static import of a constant you write it bare instead of ClassName.CONSTANT. Both forms are pure compile-time syntactic sugar: they change how you write names in source, not the generated bytecode, which still resolves to the fully-qualified member. Static imports were added in Java 5, primarily to reduce noise when a class uses a small set of static helpers or constants heavily.

go deeper

for a junior

Knows a static import lets you drop the class name when calling a static method or using a constant, e.g. max instead of Math.max.

for a middle

Can state precisely that it imports a static member (field/method), not a type, contrast it with a regular import, and note it is compile-time only.

for a senior

Explains the motivation (constants, fluent test DSLs), the Java 5 history including the constant-interface anti-pattern it replaced, and that bytecode is unchanged.

for a principal

Frames usage as a readability/maintainability policy decision across a codebase and can articulate when the lost qualifier cue outweighs brevity.

## First, what is an "import" at all? In Java every class lives in a **package** (a namespace, e.g. `java.util`). The fully-qualified name of the `List` interface is `java.util.List`. You *could* write that long name everywhere, but that's verbose. An **import statement** at the top of a file tells the compiler: "when I write the simple name `List`, I mean `java.util.List`." Imports are a **compile-time convenience only** — they don't load code, don't run anything, and don't appear in the compiled `.class` file. The bytecode always uses fully-qualified references. A regular import imports a **type** (a class, interface, enum, etc.). ## What "static" means here A member of a class is **static** when it belongs to the class itself rather than to an instance. Examples: the method `Math.max(a, b)`, the field `Math.PI`, the constant `Integer.MAX_VALUE`. You call a static member through the class name, not through an object. A **static import** imports a **static member** (a static field or static method) of a type, so you can use that member by its **simple name**, without qualifying it with the class name. ```java import static java.lang.Math.max; // import one static method import static java.lang.Math.PI; // import one static field int m = max(3, 7); // instead of Math.max(3, 7) double c = 2 * PI * r; // instead of 2 * Math.PI * r ``` Contrast with the regular import: ```java import java.lang.Math; // (java.lang is auto-imported, shown for illustration) int m = Math.max(3, 7); // still need the Math. qualifier ``` ## The two forms (covered in detail in the wildcard question) - **Single-member:** `import static java.lang.Math.max;` brings in exactly that member name. - **Wildcard:** `import static java.lang.Math.*;` brings in *all* accessible static members of `Math`. ## Why it exists Introduced in **Java 5 (2004)**, alongside generics and enums. Before it, code that used many constants either fully-qualified each one or — worse — implemented an interface full of constants just to inherit them unqualified (the discredited "constant interface" anti-pattern). Static import gave a clean, intentional alternative. The two most common, legitimate uses: (1) constant-heavy code (e.g. unit conversions), and (2) fluent test/assertion libraries such as JUnit/Hamcrest where `assertEquals(...)`, `assertThat(...)`, `is(...)` read far better unqualified. ## Key takeaways - Regular import = type by simple name. Static import = *static member* by simple name. - Both are compile-time only; bytecode is identical. - Overuse hurts readability because the reader loses the `ClassName.` cue that tells them where a name comes from.

  • Does a static import affect runtime performance?
    No. It is pure source-level sugar; the compiler resolves the unqualified name to the same fully-qualified member, so the bytecode and runtime behavior are identical.
  • Can you statically import a member of your own class in the same file?
    No, and you don't need to: static members of the current class (and its supertypes) are already accessible by simple name without any import.

saying these in an interview costs you the question

  • Saying static import imports a class (it imports a static member, not a type)
  • Claiming it changes the generated bytecode or performance
  • Confusing it with a regular import

context