The <code>static</code> Keyword in Java

static attaches a member to the class itself instead of to instances. A static field is shared across every instance (and callers who don't even have one). A static method is called via ClassName.method() and has no this.

Static fields β€” one copy per class

public class Counter {
    private static int total;          // ONE slot, shared by all instances
    private int mine;                   // one slot PER instance

    public void increment() {
        total++;
        mine++;
    }
    public static int total() { return total; }
}

Static methods

public class MathUtils {
    public static int square(int n) { return n * n; }
}
MathUtils.square(5);                    // no instance needed

Static methods can't access instance fields or call instance methods (they have no this). They also aren't polymorphic β€” the call is resolved at compile time.

Constants β€” static final

public class Config {
    public static final int MAX_RETRY = 3;
    public static final Duration TIMEOUT = Duration.ofSeconds(30);
}

Config.MAX_RETRY;

Static initialisers

public class Country {
    private static final Map<String, String> CODES;
    static {
        var m = new HashMap<String, String>();
        m.put("fr", "France");
        m.put("de", "Germany");
        CODES = Map.copyOf(m);
    }
}

Static initialisers run once, when the class is first loaded. They run before any instance is created.

Static nested classes

public class Outer {
    public static class Builder { ... }     // no reference to Outer instance
}

var b = new Outer.Builder();                 // no Outer needed

Unless a nested class truly needs access to the outer instance, make it static. A non-static inner class silently captures the outer reference β€” a memory leak waiting to happen.

Factory methods

public final class Money {
    private final BigDecimal amount;
    private final Currency   currency;
    private Money(BigDecimal amount, Currency currency) { ... }

    public static Money usd(BigDecimal amount) {
        return new Money(amount, Currency.getInstance("USD"));
    }
    public static Money zero() { return new Money(BigDecimal.ZERO, ...); }
}
Money.usd(new BigDecimal("10.50"));

Static imports

import static java.lang.Math.*;
import static org.assertj.core.api.Assertions.assertThat;

double r = sqrt(pow(x, 2) + pow(y, 2));
assertThat(value).isEqualTo(42);

Common mistakes

  • Mutable static state β€” shared across threads, a race-condition gold mine. Prefer instance state with dependency injection.
  • Static methods on everything β€” makes testing hard (can't mock). Use them for pure utilities only.
  • Non-static inner class in a long-lived collection β€” retains the outer instance forever.
  • Overriding static β€” it's not overridden, it's hidden. Only instance methods are polymorphic.

Related

Pillar: Java keywords. See also static variables, static methods, final.