W3docs

Java Non-Access-Modifier

Java-Non-Access-Modifier — static, final, abstract, synchronized, transient, volatile — und was jeder davon bewirkt.

Javas Zugriffsmodifikatoren — public, protected, private — steuern, wer auf ein Member zugreifen kann. Die Non-Access-Modifier steuern, wie es sich verhält. Es handelt sich um eine überschaubare Sammlung von Schlüsselwörtern, die Eigentümerschaft, Veränderbarkeit, Threading, Serialisierung und einige weitere Aspekte beeinflussen. Dieses Kapitel gibt einen Überblick; jeder Modifier hat an anderer Stelle ein ausführlicheres Kapitel oder einen eigenen Abschnitt.

Die vollständige Liste

ModifierGilt fürWas er bewirkt
staticFelder, Methoden, verschachtelte Klassen, BlöckeGehört zur Klasse, nicht zu Instanzen
finalKlassen, Methoden, Felder, Parameter, lokale VariablenKann nicht neu zugewiesen/überschrieben/erweitert werden
abstractKlassen, MethodenKein Rumpf / kann nicht instanziiert werden; muss von einer Unterklasse implementiert werden
synchronizedMethoden, BlöckeNur ein Thread gleichzeitig darf es an einem bestimmten Lock ausführen
volatileFelderLese-/Schreibzugriffe werden nicht im thread-lokalen Speicher gecacht
transientFelderWird bei der Standard-Serialisierung übersprungen
nativeMethodenImplementierung liegt in Nicht-Java-Code (meist C/C++)
strictfpKlassen, MethodenErzwingt strikte IEEE-754-Gleitkommaverhalten (weitgehend historisch)
defaultInterface-MethodenStellt einen Standard-Rumpf in einem Interface bereit
sealed / non-sealedKlassen, InterfacesSchränkt ein, welche Klassen erweitern dürfen (Java 17+)

static, final, abstract und default begegnen einem ständig. Die übrigen sieht man nur, wenn das jeweilige Problem auftritt.

static — gehört zur Klasse

Ein static-Member ist mit der Klasse selbst verknüpft, nicht mit einer einzelnen Instanz:

public class Counter {
  int instanceCount;          // one per Counter object
  static int classCount;      // one shared by everyone
}

static ist so verbreitet, dass es ein eigenes Kapitel bekommt — siehe java-static.

final — kann nicht geändert werden

final bedeutet: „Diese Bindung ist nach der Zuweisung unveränderlich." Es gilt für verschiedene Dinge:

final int MAX = 100;          // local variable cannot be reassigned
public final class Money {}   // class cannot be extended
public final void close() {}  // method cannot be overridden
private final int balance;    // field assigned once, then immutable

final ist die Grundlage von Konstanten (static final), unveränderlichen Objekten und sicherem Vererbungsdesign. Die vollständige Behandlung findet sich in java-final.

abstract — hat keinen Rumpf, muss ausgefüllt werden

abstract auf eine Klasse angewendet bedeutet: „Diese Klasse kann nicht direkt instanziiert werden — nur Unterklassen können es." Auf eine Methode angewendet bedeutet es: „Kein Rumpf hier — jede konkrete Unterklasse muss einen bereitstellen":

public abstract class Shape {
  public abstract double area();      // no body
}

public class Circle extends Shape {
  double r;
  public double area() { return Math.PI * r * r; }
}

new Shape() ist ein Kompilierfehler; new Circle() funktioniert. Behandelt in abstract classes.

synchronized — ein Thread gleichzeitig

Wenn zwei Threads dieselbe Methode am selben Objekt aufrufen könnten, stellt das Markieren der Methode mit synchronized sicher, dass nur einer gleichzeitig ausgeführt wird:

public synchronized void deposit(int amount) {
  balance += amount;
}

Dies ist die einfachste Form des Lockings. Im Buch gibt es später einen ganzen Abschnitt zur Nebenläufigkeit; für jetzt genügt es, das Schlüsselwort zu kennen und zu verstehen, was es grob bewirkt. Siehe synchronization für die vollständige Erklärung.

volatile — sichtbar über Threads hinweg

Ohne volatile dürfen Threads den Wert eines Feldes cachen. Lesezugriffe in einem Thread sehen unter Umständen niemals Schreibzugriffe aus einem anderen Thread:

private volatile boolean stopped = false;

volatile erzwingt, dass jeder Lesezugriff aus dem Hauptspeicher erfolgt und jeder Schreibzugriff in den Hauptspeicher geht. Es ist der leichtgewichtige Verwandte von synchronized für einfache Flag-Felder — siehe volatile für die Details zum Speichermodell.

transient — bei der Serialisierung überspringen

Javas eingebaute Objektserialisierung (Serializable) schreibt standardmäßig jedes Feld. transient sagt: „Dieses hier nicht einschließen" — typischerweise verwendet für Caches, berechnete Werte oder Dinge, die außerhalb des laufenden Programms keinen Sinn ergeben:

public class Session {
  String userId;
  transient String passwordHash;     // not serialized
}

Moderner Code verwendet häufiger JSON-Serialisierer als Serializable, aber das Schlüsselwort ist in Bibliotheken, die darauf angewiesen sind, weiterhin nützlich. Mehr in serialization.

native — anderswo implementiert

native gilt für Methoden, deren Rumpf in einer anderen Sprache geschrieben ist (C/C++ über JNI). Man schreibt sie selbst selten; man sieht sie hauptsächlich in Low-Level-Bibliotheken:

public native int currentTimeMillis();

strictfp — strikte Gleitkommaberechnung

Ursprünglich erzwang strictfp vorhersehbare IEEE-754-Gleitkommaarithmetik auf verschiedenen Plattformen. Ab Java 17 ist alle Gleitkomma-Mathematik implizit strikt, was das Schlüsselwort zu einem No-Op macht. Man kann es größtenteils ignorieren; es taucht in älteren Codebasen noch auf.

default — bei Interface-Methoden

Innerhalb eines Interface ermöglicht default, einen Rumpf für eine Methode bereitzustellen, anstatt sie abstrakt zu lassen:

public interface Greeter {
  default String greet(String name) {
    return "Hello, " + name;
  }
}

Ohne default hat eine Interface-Methode keinen Rumpf, und jede implementierende Klasse muss eine eigene Version schreiben. Vollständige Behandlung in default methods.

sealed und non-sealed

Eine sealed-Klasse benennt die genaue Liste der Klassen, die sie erweitern dürfen. Unterklassen müssen sich dann für final, sealed oder non-sealed entscheiden:

public sealed class Shape permits Circle, Square { }
public final class Circle extends Shape { }
public non-sealed class Square extends Shape { }

Nützlich für geschlossene Typhierarchien — siehe sealed classes.

Modifier kombinieren

Modifier können in der Regel frei gestapelt werden, in dieser gebräuchlichen Reihenfolge:

public  static  final   int MAX = 100;
private static  volatile int counter;
protected abstract       void onInit();

Einige Kombinationen sind unzulässig: Eine Methode kann nicht gleichzeitig abstract und final, abstract und private oder abstract und static sein. Der Compiler meldet sich, wenn eine Grenze überschritten wird.

Ein ausgearbeitetes Beispiel

java— editable, runs on the server

Was kommt als Nächstes

Die nächsten beiden Kapitel vertiefen die beiden am häufigsten verwendeten Modifier: static für Member auf Klassenebene, dann final für Unveränderlichkeit. Am besten in dieser Reihenfolge lesen.

Übungen

Übung
Welcher Non-Access-Modifier bedeutet, dass ein Klassenmember zur Klasse selbst gehört und nicht zu jeder Instanz?
Welcher Non-Access-Modifier bedeutet, dass ein Klassenmember zur Klasse selbst gehört und nicht zu jeder Instanz?
Was this page helpful?