Zur Klasse gehören, nicht zum Objekt
Die meisten Felder und Methoden, die du bisher geschrieben hast, gehören zu Objekten: Jedes Mal, wenn du new aufrufst, erhält jede Instanz ihre eigene Kopie der Felder, und Methoden arbeiten auf dem Zustand genau dieses Objekts. Das Schlüsselwort static kehrt das um. Ein static-Member gehört zur Klasse selbst - es gibt eine einzige Kopie, die von jeder Instanz geteilt wird, und sie existiert, ob du jemals ein Objekt erzeugst oder nicht.
Diese eine Unterscheidung erklärt static Felder, static Methoden, Konstanten und sogar, warum main immer static ist.
Ein geteiltes static-Feld
Ein nicht-statisches Feld gibt jedem Objekt seinen eigenen Platz. Ein static-Feld gibt der Klasse einen Platz, den alle teilen. Das klassische Beispiel ist ein Zähler, der festhält, wie viele Objekte erzeugt wurden:
Beachte, dass du den Zähler als User.count ausliest - über den Klassennamen, weil der Wert zu keinem einzelnen User gehört. Jedes name hingegen lebt in seinem eigenen Objekt. Ändere count über eine beliebige Instanz, und jede Instanz sieht den neuen Wert, weil es nur einen davon gibt.
static Methoden
Eine static-Methode gehört ebenfalls zur Klasse, daher rufst du sie auf der Klasse ohne ein Objekt auf:
Genau dieses Muster steckt hinter der Standardbibliothek: Math.max, Integer.parseInt, Arrays.sort und List.of sind alle static - Hilfsverhalten, das kein Objekt zum Arbeiten benötigt. Greife zu einer static-Methode, wenn die Arbeit nur von ihren Argumenten abhängt und nicht von irgendeinem objektspezifischen Zustand.
Der große Stolperstein: static kann instance nicht sehen
Eine static-Methode läuft ohne jedes Objekt, es gibt also kein this. Das bedeutet, sie kann Instanzfelder nicht direkt ansprechen oder Instanzmethoden aufrufen - es gibt kein bestimmtes Objekt, aus dem sie sie auslesen könnte. Das ist der mit Abstand häufigste Anfängerfehler bei static:
class Account {
int balance = 100; // Instanzfeld
static int show() {
return balance; // KOMPILIERFEHLER: auf das nicht-statische Feld 'balance'
} // kann aus einem statischen Kontext nicht zugegriffen werden
}
Die Lösung ist entweder, die Methode zu einer Instanzmethode zu machen (static entfernen, sodass sie ein this hat), oder das Objekt explizit zu übergeben:
Die umgekehrte Richtung ist unproblematisch: Eine Instanzmethode darf static-Felder frei lesen und static-Methoden aufrufen, weil die geteilten Daten auf Klassenebene immer existieren.
Konstanten mit static final
Kombinierst du static mit final, erhältst du eine Konstante: einen einzigen geteilten Wert, der sich nie ändern kann. Per Konvention werden diese in UPPER_SNAKE_CASE benannt:
static final ist die idiomatische Art, „einen festen Wert, der zum Typ gehört" auszudrücken - Dinge wie Integer.MAX_VALUE oder Math.PI in der Standardbibliothek. Es static zu machen bedeutet, dass du nicht pro Objekt eine Kopie verschwendest; es final zu machen bedeutet, dass niemand es neu zuweisen kann.
static Initialisierungsblöcke
Ein einfaches static-Feld kann inline initialisiert werden. Wenn die Einrichtung echte Logik benötigt - eine Nachschlagetabelle aufbauen, Konfiguration lesen - verwende einen static-Block. Er läuft einmal, wenn die Klasse zum ersten Mal geladen wird, bevor irgendein Objekt existiert:
Der Block wird ein einziges Mal ausgelöst, egal wie oft du die Klasse verwendest, was ihn zum richtigen Ort für eine einmalige, klassenweite Einrichtung macht.
Wann man static verwendet
Eine schnelle Faustregel:
- Verwende ein static Feld nur für Daten, die wirklich von allen Instanzen geteilt werden - einen Zähler, einen Cache, eine Konstante. Wenn zwei Objekte vernünftigerweise unterschiedliche Werte halten könnten, sollte es stattdessen ein Instanzfeld sein.
- Verwende eine static Methode, wenn das Ergebnis nur von den Argumenten abhängt und nicht vom Zustand eines Objekts (reine Hilfsfunktionen).
- Bevorzuge standardmäßig Instanz-Member. Übermäßiger Einsatz von
staticverwandelt dein Programm stillschweigend in einen Haufen globalen Zustands, der schwer zu testen und nachzuvollziehen ist.staticist die Ausnahme, nicht der Ausgangspunkt.
Als Nächstes: Enums
Eine static final-Konstante eignet sich für einen einzelnen festen Wert, aber wenn du eine kleine, feste Menge verwandter Werte hast - Richtungen, Wochentage, Bestellstatus - bietet Java einen eigens dafür gemachten Typ, der sicherer und ausdrucksstärker ist als verstreute Konstanten. Das ist das enum, und es ist die nächste Seite.
Häufig gestellte Fragen
Was bedeutet static in Java?
static bedeutet, dass ein Feld oder eine Methode zur Klasse selbst gehört, nicht zu einem einzelnen Objekt. Von einem static-Feld gibt es genau eine Kopie, die von jeder Instanz geteilt wird, und eine static-Methode wird auf der Klasse (Math.max(...)) aufgerufen, ohne dass man ein Objekt braucht. Nicht-statische (Instanz-)Member erhalten dagegen pro Objekt eine eigene Kopie.
Was ist der Unterschied zwischen static und Instanzvariablen in Java?
Eine Instanzvariable hat einen Wert pro Objekt - zwei Objekte können unterschiedliche Werte halten. Eine static-Variable hat einen einzigen Wert, der von allen Objekten der Klasse geteilt wird; ändert man ihn über ein Objekt (oder über den Klassennamen), ist das für jedes andere sichtbar. Verwende Instanzfelder für den Zustand pro Objekt und static-Felder für Daten, die wirklich klassenweit global sind, wie einen Zähler oder eine Konstante.
Warum ist die main-Methode in Java static?
Die JVM muss main aufrufen, bevor irgendein Objekt deiner Klasse existiert. Da eine static-Methode zur Klasse und nicht zu einer Instanz gehört, kann die Laufzeit Main.main(args) direkt aufrufen, ohne zuvor ein Main zu erzeugen. Deshalb lautet die Signatur immer public static void main(String[] args).