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:
| Modifikator | Sichtbar von |
|---|---|
public | Überall |
protected | Gleiches Paket oder jede Unterklasse (auch in einem anderen Paket) |
| (kein Schlüsselwort) | Nur gleiches Paket — package-private |
private | Nur 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 thisVerwende 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 privateDas 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 nurpublicoder 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 classDie 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:
- Standardmäßig
privatefür Felder und Hilfsmethoden. publicfür die Methoden, die tatsächlich von außen aufgerufen werden sollen.- Package-private für Dinge, die innerhalb eines Pakets geteilt werden müssen, aber nicht nach außen sichtbar sein sollen.
protectednur, wenn explizit auch Unterklassen-Zugriff gewünscht ist.
Der Zugriff kann später leicht erweitert werden (private → public); 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
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.