W3docs

Java Zugriffsmodifikatoren

Sichtbarkeit in Java steuern mit public, private, protected und package-private (default) Zugriffsmodifikatoren.

Zugriffsmodifikatoren legen fest, wer eine Klasse, ein Feld, eine Methode oder einen Konstruktor sehen und verwenden darf. Java kennt vier Ebenen — public, protected, package-private (kein Schlüsselwort) und private — die von "die ganze Welt" bis "nur diese Klasse" reichen. Die richtige Wahl ist der Weg, eine Grenze zwischen der Schnittstelle eines Objekts und seinen internen Details zu ziehen.

Die vier Ebenen

Von der freizügigsten zur restriktivsten:

ModifikatorSichtbar von
publicÜberall
protectedGleiches Paket oder jede Unterklasse (auch in einem anderen Paket)
(kein Schlüsselwort)Nur gleiches Paket — package-private
privateNur die gleiche Klasse

Das war's. Kein "friend", kein "module-internal" auf dieser Ebene; Modulsichtbarkeit ist eine separate Funktion des Java Platform Module System, die man meistens nicht benötigt.

public

Ein public-Member gehört zur veröffentlichten API der Klasse — er ist für jeden Code sichtbar, der die Klasse selbst sehen kann:

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

new Greeter().greet("world");    // anyone can call this

Verwende public für Dinge, die anderer Code — auch andere Projekte — aufrufen soll. Der Nachteil: Sobald etwas public ist, hast du dich dazu verpflichtet; das Ändern der Signatur bricht jeden Aufrufer.

private

private beschränkt einen Member auf seine deklarierende Klasse. Nichts außerhalb kann ihn berühren — nicht einmal eine Unterklasse:

public class Account {
  private int balance;     // only Account can read/write

  public void deposit(int amount) {
    if (amount <= 0) throw new IllegalArgumentException();
    balance += amount;      // ok — same class
  }
}

Account a = new Account();
a.balance = -1;             // ERROR — balance is private

Das ist das Arbeitspferd für Felder. Das Verstecken von Zustand hinter private ist das, was die Validierung in deposit tatsächlich bedeutungsvoll macht. Das Kapitel zur Kapselung geht auf das Muster ein.

Package-private (kein Schlüsselwort)

Lässt man den Modifikator vollständig weg, ist der Member für alles im gleichen Paket sichtbar — aber für nichts außerhalb:

// in package com.shop
class CartHelper {           // no public — package-private
  static int sum(int[] prices) { ... }
}

Andere Klassen in com.shop können CartHelper.sum(...) aufrufen; Code in com.app kann die Klasse nicht einmal sehen. Verwende dies für interne Hilfsmethoden, die das Paket intern teilen muss, die aber nicht zur öffentlichen API des Projekts gehören.

Ein häufiger Fehler: den Modifikator vergessen und dann überrascht sein, wenn die Klasse von main aus verwendet werden kann (ebenfalls im gleichen Paket beim Lernen), aber nicht von einem Test in einem anderen Paket.

protected

protected ist package-private plus Unterklassen. Code im gleichen Paket kann den Member verwenden, und jede Unterklasse — auch eine in einem anderen Paket — kann ihn verwenden:

public class Shape {
  protected double area;       // subclasses can read/write
}

public class Circle extends Shape {
  Circle(double r) {
    this.area = Math.PI * r * r;   // ok — subclass access
  }
}

Das ist die Wahl, wenn Unterklassen in die Maschinerie der Elternklasse eingreifen sollen, ohne dass allgemeiner Client-Code sie berühren kann. In der Praxis taucht protected weit seltener auf als public oder private; viele Designer bevorzugen private-Felder mit protected-Accessor-Methoden für denselben Effekt mit mehr Kontrolle.

Wo Modifikatoren anwendbar sind

Ein Modifikator kann gesetzt werden auf:

  • Eine Klasse selbst (public class Foo). Klassen auf oberster Ebene können nur public oder package-private sein. Innere Klassen können eines der vier sein.
  • Ein Feld (private int count).
  • Eine Methode (public int get() {...}).
  • Einen Konstruktor (private Singleton() {...} — siehe Singleton-Muster).

Ein Zugriffsmodifikator kann nicht auf eine lokale Variable oder einen Methodenparameter gesetzt werden. Diese werden ausschließlich durch ihren Deklarationsort abgegrenzt.

Die "eine public-Klasse pro Datei"-Regel

Eine .java-Datei darf mehrere Klassen auf oberster Ebene deklarieren, aber höchstens eine davon kann public sein, und deren Name muss mit dem Dateinamen übereinstimmen:

// file: Order.java
public class Order { ... }          // ok — matches filename
class OrderHelper { ... }           // ok — package-private
public class Customer { ... }       // ERROR — second public class

Die meisten Projekte halten sich an eine Klasse pro Datei, aber package-private Hilfsklassen neben einer public-Klasse sind manchmal nützlich.

Die richtige Wahl treffen

Eine Faustregel, die gut skaliert:

  1. Standardmäßig private für Felder und Hilfsmethoden.
  2. public für die Methoden, die tatsächlich von außen aufgerufen werden sollen.
  3. Package-private für Dinge, die innerhalb eines Pakets geteilt werden müssen, aber nicht nach außen sichtbar sein sollen.
  4. protected nur, wenn explizit auch Unterklassen-Zugriff gewünscht ist.

Der Zugriff kann später leicht erweitert werden (privatepublic); ihn einzuengen, ohne Aufrufer zu brechen, ist schmerzhaft. Fange eng an.

Modifikatoren ändern kein Verhalten

Ein Zugriffsmodifikator ist eine Prüfung zur Kompilierzeit. Zur Laufzeit verhalten sich zwei gleiche int-Felder identisch, egal ob sie als public oder private deklariert wurden. Der Modifikator existiert ausschließlich dazu, anderen Code am Kompilieren gegen den Member zu hindern — um eine Grenze durchzusetzen, die du deklarierst.

Ein ausgearbeitetes Beispiel

java— editable, runs on the server

Was kommt als Nächstes

public, protected, private sind Zugriffsmodifikatoren. Java hat eine weitere Familie — die Nicht-Zugriffsmodifikatoren wie static, final, abstract, synchronized — die das Verhalten statt der Sichtbarkeit steuern. Das nächste Kapitel, Nicht-Zugriffsmodifikatoren, gibt einen Überblick über diese.

Übung

Übung
Ein Feld wird ohne Zugriffsmodifikator deklariert — nur int count;. Wer kann es lesen?
Ein Feld wird ohne Zugriffsmodifikator deklariert — nur int count;. Wer kann es lesen?
Was this page helpful?