Wer deinen Code anfassen darf
Ein Zugriffsmodifikator ist ein Schlüsselwort vor einer Klasse, einem Feld, einer Methode oder einem Konstruktor, das entscheidet, wer ihn sonst noch verwenden darf. Er ist das Fundament der Kapselung: Du versteckst das chaotische Innenleben einer Klasse und legst nur die Teile offen, von denen du darauf vertraust, dass anderer Code sie aufruft.
Java hat vier Ebenen, von der offensten zur am stärksten abgeschotteten: public, protected, default (überhaupt kein Schlüsselwort) und private. Wenn du sie richtig wählst, wird eine Klasse später sicher änderbar, weil nichts außerhalb von Details abhängt, deren Beibehaltung du nie zugesagt hast.
private: nur innerhalb der Klasse sichtbar
private ist die strengste Ebene. Auf ein private Element kann nur Code zugreifen, der innerhalb derselben Klasse geschrieben wurde - keine Unterklassen, keine anderen Klassen im selben Paket, niemand. Hier gehören die meisten deiner Felder hin.
balance ist private, also ist der einzige Weg, es zu ändern, über deposit, das negative Beträge ablehnt. Wäre balance public, könnte beliebiger Code account.balance = -9999 schreiben und die Prüfung vollständig umgehen. Diese Absicherung ist der ganze Sinn dahinter, das Feld zu verstecken.
Versuche, account.balance = 500; in main zu entkommentieren, und du erhältst einen Kompilierfehler: balance has private access in BankAccount.
public: überall sichtbar
public ist das gegenteilige Extrem - jeder, überall, kann das Element verwenden. Die Namen deiner Methoden, die anderer Code aufrufen soll, sind meist public. Das gilt auch für die Klasse selbst, wenn sie aus anderen Paketen erreichbar sein muss.
Das übliche Muster - manchmal die öffentliche API einer Klasse genannt - lautet: private Felder, public Methoden. Die Felder halten den Zustand, an dem niemand sonst herumstochern sollte; die Methoden sind die kontrollierten Türen hinein und hinaus. getBalance und deposit oben sind genau das.
default (package-private): überhaupt kein Schlüsselwort
Wenn du keinen Modifikator schreibst, erhältst du default-Zugriff, auch package-private genannt. Das Element ist für jede Klasse im selben Paket sichtbar und für alles außerhalb unsichtbar. Für diese Ebene gibt es kein Schlüsselwort - das Fehlen eines Schlüsselworts ist die Ebene.
class Invoice { // kein Modifikator -> nur innerhalb dieses Pakets sichtbar
int amount; // kein Modifikator -> package-private Feld
}
Das erwischt viele Anfänger: public wegzulassen macht etwas nicht private, sondern package-private. Ein Feld, das du geheim halten wolltest, ist immer noch vollständig lesbar und schreibbar durch jede Klasse, die zufällig im selben Paket liegt. Wenn du willst, dass es wirklich versteckt ist, musst du private ausdrücklich schreiben.
Default-Zugriff ist tatsächlich nützlich für Hilfsklassen, die ein Implementierungsdetail eines Pakets sind - du exportierst sie nicht, aber Klassen, die innerhalb des Pakets zusammenarbeiten, können sie trotzdem frei verwenden.
protected: Paket plus Unterklassen
protected ist eine Stufe lockerer als default. Ein protected Element ist überall dort sichtbar, wo default es ist (im selben Paket), und außerdem in Unterklassen - sogar in Unterklassen in einem anderen Paket. Es ist für Dinge gedacht, die du mit Klassen teilen willst, die deine erweitern, aber nicht mit der ganzen Welt.
Dog greift auf name und sound() zu, weil sie protected sind und Dog eine Unterklasse ist. Externer Code, der keine Unterklasse ist und nicht im Paket liegt, kann sie weiterhin nicht anfassen. Greife zu protected, wenn du eine Klasse entwirfst, die erweitert werden soll; andernfalls bevorzuge private.
Die vier Ebenen auf einen Blick
Hier das vollständige Bild, vom restriktivsten zum offensten:
| Modifikator | Gleiche Klasse | Gleiches Paket | Unterklasse (anderes Paket) | Überall |
|---|---|---|---|---|
private | ja | nein | nein | nein |
| default | ja | ja | nein | nein |
protected | ja | ja | ja | nein |
public | ja | ja | ja | ja |
Eine einfache Faustregel: Beginne mit private und lockere nur dann, wenn etwas wirklich breiteren Zugriff braucht. Es ist viel einfacher, den Zugriff später zu erweitern, als ihn einzuschränken, sobald anderer Code begonnen hat, von einem Element abzuhängen.
Modifikatoren an den Klassen selbst
Zugriffsmodifikatoren gelten auch für Klassen, nicht nur für Elemente - aber eine Top-Level-Klasse (eine, die nicht in einer anderen verschachtelt ist) kann nur public oder default sein. Du kannst keine private oder protected Top-Level-Klasse schreiben.
public class Order { ... } // aus jedem Paket erreichbar
class LineItem { ... } // default - nur dieses Paket kann sie sehen
Eine public Top-Level-Klasse muss in einer Datei liegen, die nach ihr benannt ist (Order.java). Verschachtelte Klassen hingegen können alle vier Modifikatoren verwenden - deshalb konnten die obigen Beispiele innere Klassen als private oder default markieren. Ein feiner Punkt: Eine public Methode, die einen package-private Typ zurückgibt, ist für externe Aufrufer nicht sehr nützlich, also halte deine öffentliche Oberfläche konsistent.
Als Nächstes: Statische Member
Bisher gehört hier jedes Feld und jede Methode zu einer Instanz - du erstellst ein Objekt mit new und rufst dann Methoden darauf auf. Aber manchmal gehört ein Wert oder ein Verhalten zur Klasse als Ganzes, geteilt über alle Instanzen hinweg, wie etwa ein Zähler dafür, wie viele Objekte existieren. Genau dafür ist das Schlüsselwort static da, und es kommt als Nächstes.
Häufig gestellte Fragen
Was sind die vier Zugriffsmodifikatoren in Java?
public, private, protected und das default (kein Schlüsselwort, auch package-private genannt). public ist überall sichtbar, private nur innerhalb derselben Klasse, protected innerhalb des Pakets plus in Unterklassen, und default nur innerhalb desselben Pakets.
Was ist der Unterschied zwischen public und private in Java?
public bedeutet, dass beliebiger Code von überall auf das Element zugreifen kann. private bedeutet, dass nur Code innerhalb derselben Klasse das kann - Unterklassen und andere Klassen können es nicht einmal sehen. Üblicherweise macht man Felder private und stellt sie über public Methoden bereit.
Was bedeutet es, wenn ein Java-Feld keinen Zugriffsmodifikator hat?
Kein Schlüsselwort bedeutet default-Zugriff (package-private): Das Element ist für jede Klasse im selben Paket sichtbar, außerhalb davon aber unsichtbar. Es ist strenger als public, aber lockerer als private - und man lässt es leicht aus Versehen weg, also sei bewusst damit.