W3docs

Java static-Schlüsselwort

Klassenmitglieder in Java mit static deklarieren – statische Felder, Methoden, Blöcke und verschachtelte Klassen.

static ist das Schlüsselwort, das ein Klassenmitglied von „einmal pro Instanz" zu „einmal pro Klasse" hochstuft. Ein statisches Feld hat eine einzige Kopie, die von allen Objekten geteilt wird. Eine statische Methode gehört zur Klasse selbst und läuft ohne eine Instanz. Ein statischer Block wird einmal ausgeführt, wenn die Klasse erstmals geladen wird. Eine statisch verschachtelte Klasse lebt innerhalb einer anderen Klasse, ohne ein umschließendes Objekt zu benötigen.

Die einzige Faustregel: static-Mitglieder haben kein this. Alles andere über ihr Verhalten ergibt sich daraus.

Statische Felder

Ein statisches Feld wird mit static im Klassenkörper deklariert. Es gibt genau eine Kopie, unabhängig davon, wie viele Instanzen existieren:

public class Counter {
  static int total;       // one Counter.total for everybody
  int count;              // each Counter has its own count
}

Counter a = new Counter();   a.count++;   Counter.total++;
Counter b = new Counter();   b.count++;   Counter.total++;

System.out.println(a.count);          // 1
System.out.println(b.count);          // 1
System.out.println(Counter.total);    // 2

Ein statisches Feld wird über den Klassennamen angesprochen (Counter.total) – das ist die kanonische Form. Java erlaubt auch a.total, weil a ein Counter ist, aber jeder Linter der Welt markiert diesen Stil.

Statische Methoden

Eine statische Methode gehört zur Klasse. Rufen Sie sie mit KlassenName.methode(...) auf:

public class MathUtil {
  public static int square(int n) {
    return n * n;
  }
}

int x = MathUtil.square(7);     // 49

Innerhalb einer statischen Methode gibt es kein this — Sie können keine Instanzfelder lesen oder Instanzmethoden unqualifiziert aufrufen, weil es keine aktuelle Instanz gibt, von der sie gelesen werden könnten:

public class Counter {
  int count;
  static void reset() {
    count = 0;      // ERROR: cannot reference instance field from static context
  }
}

Sie können trotzdem eine Instanz als Parameter nehmen und damit arbeiten:

static void resetThis(Counter c) {
  c.count = 0;     // ok — c is a parameter, not this
}

Die umgekehrte Richtung funktioniert einwandfrei: Eine Instanzmethode kann eine statische Methode ohne Umstände aufrufen, weil die Klasse immer vorhanden ist, auch wenn eine Instanz existiert.

Wann static verwenden

Der einzige Test ist, ob das Mitglied von einem instanzspezifischen Zustand abhängt.

Hängt von this ab?Verwenden
Nein — reine Berechnung, gemeinsamer Zähler, Factory-Methodestatic
Ja — liest oder schreibt die eigenen Felder des ObjektsInstanz
public static int hoursToSeconds(int h) { return h * 3600; }   // no this needed → static
public        int rentalDays()           { return days; }       // reads this.days → instance

Ein häufiges Anzeichen: Eine Instanzmethode, die this ignoriert. Sie gibt fälschlicherweise vor, instanzspezifisch zu sein — machen Sie sie static, und der Aufrufer muss kein Objekt mehr erfinden, nur um sie zu nutzen.

Statische Konstanten

Die Kombination static final ist die Standardform für Konstanten:

public static final double TAX_RATE = 0.08;
public static final int    MAX_RETRIES = 3;
public static final String DEFAULT_LOCALE = "en";

Gemäß Konvention werden Konstanten als UPPER_SNAKE_CASE benannt. Sie werden zur Kompilierzeit eingebettet, wenn der Wert primitiv oder ein String-Literal ist, was sie genauso schnell wie ein Literal an der Aufrufstelle macht.

Statische Blöcke

Ein static { ... }-Block wird einmal ausgeführt, wenn die Klasse erstmals in die JVM geladen wird. Verwenden Sie ihn für die einmalige Initialisierung statischer Felder, die mehr als einen einzelnen Ausdruck benötigen:

public class Lookup {
  static final Map<String, Integer> WEEKDAYS = new HashMap<>();
  static {
    WEEKDAYS.put("Mon", 1);
    WEEKDAYS.put("Tue", 2);
    WEEKDAYS.put("Wed", 3);
    WEEKDAYS.put("Thu", 4);
    WEEKDAYS.put("Fri", 5);
    WEEKDAYS.put("Sat", 6);
    WEEKDAYS.put("Sun", 7);
  }
}

Statische Blöcke sind mächtig, werden aber leicht überstrapaziert. Bevorzugen Sie einen einfachen Feldinitialisierer, wenn ein Ausdruck ausreicht.

Statische Felder und statische Blöcke werden von oben nach unten in der Reihenfolge ausgeführt, in der sie im Quellcode erscheinen. Wenn ein Initialisierer ein Feld (über eine Methode) erreicht, bevor die eigene Zeile dieses Feldes ausgeführt wurde, sieht er den Standardwert (0, false oder null) — die Reihenfolge ist also wichtig:

public class Order {
  static int a = compute();          // runs first; b is still 0 → a becomes 1
  static int b = 10;                 // runs second
  static int compute() { return b + 1; }
}
// Order.a == 1, Order.b == 10

(b direkt in dieser ersten Zeile zu lesen — static int a = b + 1; — wäre stattdessen ein Kompilierfehler wegen „illegal forward reference"; nur der indirekte Weg über eine Methode legt den Standardwert offen.)

Statisch verschachtelte Klassen

Eine Klasse, die innerhalb einer anderen Klasse als static deklariert ist, ist eine statisch verschachtelte Klasse. Im Gegensatz zu einer nicht-statischen inneren Klasse trägt sie keine implizite Referenz auf eine Instanz der äußeren Klasse:

public class Outer {
  static class Inner {           // does not need an Outer instance
    void hello() { System.out.println("hi"); }
  }
}

Outer.Inner i = new Outer.Inner();   // create directly
i.hello();

So haben wir Hilfsklassen in früheren static class Foo {...}-Blöcken in derselben Datei wie main gepackt — main ist statisch, also muss auch die Hilfsklasse statisch sein, damit sie ohne eine umschließende Outer-Instanz instanziiert werden kann. Das Kapitel über verschachtelte Klassen behandelt alle vier Varianten.

static ist nicht „der Konstruktor"

Einsteiger verwechseln manchmal „static = läuft einmal" mit „static = läuft bei der Objekterstellung". Die statische Initialisierung geschieht einmal pro Klasse, nicht einmal pro Objekt. Der Konstruktor läuft einmal pro Objekt. Sie sind unterschiedliche Mechanismen und werden in verschiedenen Situationen ausgelöst.

Statische Mitglieder in Interfaces

Interfaces können auch static-Methoden haben. Sie verhalten sich genauso wie Klassen-Statics — rufen Sie sie mit InterfaceName.methode(...) auf:

public interface Path {
  static Path of(String s) { return new SimplePath(s); }
}

Path p = Path.of("/tmp/foo");

Das Kapitel über Interfaces behandelt, wann das sinnvoll ist (Factory-Methoden auf dem Interface selbst).

Ein ausgearbeitetes Beispiel

java— editable, runs on the server

Dieses Programm gibt aus:

#1  apple   base=0.50 USD,  with tax=0.54
#2  bread   base=2.40 USD,  with tax=2.59
#3  butter  base=3.10 USD,  with tax=3.35
Total items ever created: 3

Beachten Sie, wie das Beispiel alle vier Varianten kombiniert: Die Konstanten und die Lookup-Tabelle werden gefüllt, bevor ein Item existiert, jedes Item behält seinen eigenen name und basePrice, und das einzige gemeinsame itemsCreated-Feld vergibt die laufende id.

Was kommt als Nächstes

static lässt Sie sagen, wem ein Mitglied gehört. Das nächste Gegenstück ist final, das festlegt, ob es sich ändern kann. Zusammen bildet static final die Standardform für Konstanten; allein formt final die Vererbung und das unveränderliche Design. Weiter zu java-final.

Übungen

Übung
Warum bekommt eine statische Methode einen Kompilierfehler, wenn sie versucht, ein Instanzfeld bei seinem bloßen Namen zu lesen?
Warum bekommt eine statische Methode einen Kompilierfehler, wenn sie versucht, ein Instanzfeld bei seinem bloßen Namen zu lesen?
Was this page helpful?