CodeGym /Kurse /JAVA 25 SELF /Zugriffsmodifizierer

Zugriffsmodifizierer

JAVA 25 SELF
Level 15 , Lektion 1
Verfügbar

1. Überblick über die Zugriffsmodifikatoren

In Java gibt es vier Zugriffsebenen für Klassen, Felder, Methoden und Konstruktoren:

Modifikator Wo ist er verfügbar?
public
Überall: in der Klasse selbst, in anderen Klassen, in anderen Paketen
protected
In der Klasse, in Unterklassen (Erben), in anderen Klassen desselben Pakets
(package-private)
Nur innerhalb des Pakets (wenn kein Modifikator explizit angegeben ist)
private
Nur innerhalb der aktuellen Klasse

Schauen wir uns jeden davon genauer an – mit Beispielen, ein paar Witzen und unerwarteten Wendungen.

public – öffentlicher Zugriff

public ist wie eine Ankündigung an die ganze Welt: „Allen ist der Zutritt erlaubt!“. Wenn eine Klasse, ein Feld, eine Methode oder ein Konstruktor als public deklariert ist, kann man von jeder anderen Klasse, sogar aus einem anderen Paket, darauf zugreifen.

Beispiel:

public class Cat {
    public String name;
    public void sayMeow() {
        System.out.println("Miau!");
    }
}

Auf diese Klasse und ihre Felder/Methoden kann man von überall zugreifen. Das ist praktisch, wenn Ihre Klasse für alle zugänglich sein soll – zum Beispiel wenn Sie eine Bibliothek schreiben.

Aber! Öffentliche Felder sind nicht immer eine gute Idee (siehe die vorherige Vorlesung). Üblicherweise macht man nur die Methoden public, die von außen erreichbar sein müssen, während Felder fast immer private bleiben.

private – Zugriff nur innerhalb der Klasse

private ist wie ein Tresor mit Zahlenschloss: Niemand außer der Klasse selbst hat Zugriff auf diese Member. Selbst Unterklassen (Subklassen) sehen private Felder und Methoden nicht!

Beispiel:

public class Cat {
    private String secretName;

    public void setSecretName(String name) {
        secretName = name;
    }

    public String getSecretName() {
        return secretName;
    }
}

Hier kann secretName in anderen Klassen weder direkt gelesen noch verändert werden. Nur Cat selbst (bzw. seine Methoden) kann das. Das ist die Grundlage der Kapselung: Wir verbergen interne Details und stellen den Zugriff nur über Methoden bereit.

protected – geschützter Zugriff

protected ist wie ein VIP-Ausweis: Zugriff haben die Klasse selbst, ihre Unterklassen (auch wenn diese in anderen Paketen liegen) sowie alle Klassen innerhalb desselben Pakets.

Beispiel:

public class Animal {
    protected int age;

    protected void growOlder() {
        age++;
    }
}

Nun kann jede Klasse, die Animal erweitert, auf das Feld age und die Methode growOlder() zugreifen.

public class Cat extends Animal {
    public void haveBirthday() {
        growOlder();
        System.out.println("Die Katze ist " + age + " Jahre alt!");
    }
}

Außerdem haben alle Klassen im selben Paket Zugriff auf protected-Member.

(package-private) – Zugriff innerhalb des Pakets

Wenn Sie überhaupt keinen Zugriffsmodifikator angeben, gilt ein Klassenmitglied als package-private (oder „Standardzugriff“). Das ist wie eine Tür ohne Schloss, aber nur für die eigenen Leute: Zugriff haben nur Klassen aus demselben Paket.

Beispiel:

class Dog {
    String name; // package-private
    void bark() { // package-private
        System.out.println("Wuff!");
    }
}

Die Klasse Dog, ihr Feld name und die Methode bark() sind nur innerhalb desselben Pakets zugänglich. Ein Zugriff aus einem anderen Paket führt zu einem Kompilierfehler.

2. Einsatz der Modifikatoren bei Feldern und Methoden

Warum Felder fast immer private sind

Die Felder einer Klasse sind ihr interner Zustand. Lässt man sie öffentlich, kann beliebiger externer Code sie jederzeit verändern. Das ist, als würden Sie fremden Kindern erlauben, mit Ihren Möbeln wie mit Lego zu spielen: Eines Tages wachen Sie auf und der Kühlschrank steht kopfüber im Badezimmer.

Beispiel für schlechte Kapselung:

public class Person {
    public String name;
    public int age;
}

Beispiel für gute Kapselung:

public class Person {
    private String name;
    private int age;

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

Methoden (Getter und Setter) ermöglichen zu steuern, wie externe Klassen Felder verändern dürfen. Zum Beispiel kann man ein negatives Alter verbieten.

Wann macht man Methoden public, protected oder package-private

  • public – wenn die Methode für alle zugänglich sein soll. In der Regel ist das die Hauptfunktionalität der Klasse.
  • protected – wenn die Methode nur für Unterklassen oder innerhalb des Pakets benötigt wird (zum Beispiel Hilfsmethoden, die in abgeleiteten Klassen nützlich sein können).
  • package-private – wenn die Methode nur innerhalb des Pakets gebraucht wird, aber von außen nicht verfügbar sein soll (zum Beispiel Implementierungsdetails).
  • private – wenn die Methode nur innerhalb der Klasse selbst verwendet wird (zum Beispiel Hilfsmethoden für die interne Logik).

Beispiel:

public class BankAccount {
    private double balance;

    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
        }
    }

    protected void applyInterest() {
        balance *= 1.05;
    }

    void internalAudit() {
        // package-private: nur für Klassen innerhalb des Pakets
    }

    private void logAction(String action) {
        // nur für interne Zwecke der Klasse
    }
}

3. Codebeispiele: eine Klasse mit verschiedenen Zugriffsebenen

Erstellen wir eine Klasse, die alles enthält: öffentliche, private, geschützte und paketweite Member. Außerdem versuchen wir, von anderen Klassen darauf zuzugreifen und sehen, was passiert.

package zoo;

public class Animal {
    public String publicName = "Für alle zugänglich";
    protected String protectedName = "Nur für Unterklassen und Paket";
    String packageName = "Nur für das Paket";
    private String privateName = "Nur für Animal";

    public void publicMethod() {
        System.out.println("Öffentliche Methode");
    }

    protected void protectedMethod() {
        System.out.println("Geschützte Methode");
    }

    void packageMethod() {
        System.out.println("Paket-Methode");
    }

    private void privateMethod() {
        System.out.println("Private Methode");
    }
}

Nun versuchen wir, auf diese Member aus einer anderen Klasse im selben Paket zuzugreifen:

package zoo;

public class Main {
    public static void main(String[] args) {
        Animal animal = new Animal();
        System.out.println(animal.publicName);      // OK
        System.out.println(animal.protectedName);   // OK
        System.out.println(animal.packageName);     // OK
        System.out.println(animal.privateName);  // Fehler: private
        animal.publicMethod();                      // OK
        animal.protectedMethod();                   // OK
        animal.packageMethod();                     // OK
        animal.privateMethod();                  // Fehler: private
    }
}

Und nun versuchen wir den Zugriff aus einem anderen Paket:

package other;

import zoo.Animal;

public class Test {
    public static void main(String[] args) {
        Animal animal = new Animal();
        System.out.println(animal.publicName);      // OK
        System.out.println(animal.protectedName); // Fehler: protected
        System.out.println(animal.packageName);   // Fehler: package-private
        System.out.println(animal.privateName);   // Fehler: private
        animal.publicMethod();                      // OK
        animal.protectedMethod();                // Fehler: protected
        animal.packageMethod();                  // Fehler: package-private
        animal.privateMethod();                  // Fehler: private
    }
}

Fazit:

  • public – überall zugänglich.
  • protected – innerhalb des Pakets und in Unterklassen zugänglich (auch aus anderen Paketen über Vererbung).
  • package-private – nur innerhalb des Pakets.
  • private – nur innerhalb der Klasse.

4. Best Practices: wie man den Zugriffsmodifikator wählt

Minimieren Sie die Sichtbarkeit

Je weniger Code ein Feld oder eine Methode sehen kann, desto besser. Öffnen Sie nur das, was externer Code wirklich benötigt. Das nennt man das Prinzip der geringsten Rechte.

  • Felder sollten fast immer private sein. Ausnahmen gelten nur für echte Konstanten (public static final), mehr dazu in den nächsten Vorlesungen.
  • Methoden macht man public nur, wenn sie Teil der externen Schnittstelle der Klasse sind.
  • Hilfsmethoden (interne Logik) – private.
  • Methoden für Unterklassenprotected.
  • Interne Servicemethoden für das Paketpackage-private.

Warum ist das wichtig?

  • Jede Änderung an Implementierungsdetails kann fremden Code brechen, wenn diese Details offengelegt sind.
  • Die Klasse wird schwerer zu testen und zu warten.
  • Zufällige Fehler (zum Beispiel eine falsche Feldänderung) können zu Bugs führen.

Manchmal denken Einsteiger: „Wozu diese Umstände, machen wir doch einfach alles public!“ Doch wenn das Projekt wächst, muss man irgendwann die halbe Anwendung umbauen, nur weil jemand Felder der Klasse direkt verändert hat.

5. Typische Fehler beim Umgang mit Zugriffsmodifikatoren

Fehler Nr. 1: Felder public gelassen oder standardmäßig package-private.
Wenn kein Modifikator angegeben wird, ist ein Feld oder eine Methode für alle Klassen innerhalb des Pakets zugänglich. Das kann zu unerwarteten Situationen führen, wenn jemand beginnt, Ihre Felder direkt zu ändern.

Fehler Nr. 2: Versuch, auf ein private-Member aus einer anderen Klasse zuzugreifen.
Der Compiler lässt das nicht zu – es gibt einen Fehler. Wenn Sie das jedoch über Reflection (Reflexion) umgehen wollen – willkommen in einer Welt voller Bugs und unerwarteter Abstürze.

Fehler Nr. 3: Zu viel public.
Wenn man alles wahllos als public deklariert, wird die Klasse zu einer offenen Kiste voller Kabel – jeder kann am falschen Kabel ziehen und alles kaputtmachen.

Fehler Nr. 4: Sie verwenden protected nicht für Methoden, die nur für Unterklassen gedacht sind.
Wenn eine Methode nur zur Erweiterung in abgeleiteten Klassen benötigt wird, deklarieren Sie sie als protected und nicht als public.

Fehler Nr. 5: Implizite package-private-Sichtbarkeit.
Man vergisst manchmal, den Modifikator anzugeben, und die Methode wird für das gesamte Paket zugänglich. Das kann überraschen, wenn man dachte, sie sei private.

Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION