Java Academy · Lektion

Innere Klassen und Zugriff auf die äußere Klasse

Verwenden Sie nicht statische innere Klassen, die eine Referenz auf die Instanz der äußeren Klasse halten.

Lektion 2 von 413 Schritte

Innere Klassen und Zugriff auf die äußere Klasse ist eine kostenlose Java Academy-Lektion auf CoddyKit. Dies ist Lektion 2 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Java Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Java Academy-Kurs umfasst insgesamt 4 Lektionen.

Innere Klassen

Eine nicht statische innere Klasse enthält eine implizite Referenz auf die Instanz der äußeren Klasse. Sie kann auf alle Member der äußeren Klasse zugreifen, einschließlich privater Member.

Eine innere Klasse deklarieren und verwenden

Erstellen Sie eine Instanz einer inneren Klasse nur über eine Instanz der äußeren Klasse mit outer.new InnerClass().

class BankAccount {
    private double balance;
    private String owner;

    BankAccount(String owner, double initial) {
        this.owner = owner; this.balance = initial;
    }

    class Transaction {
        void deposit(double amount) {
            balance += amount; // accesses outer field directly
            System.out.println(owner + " deposited " + amount);
        }
    }
}

BankAccount acct = new BankAccount("Alice", 500);
BankAccount.Transaction tx = acct.new Transaction();
tx.deposit(100); // Alice deposited 100.0

Auf Member der äußeren Klasse zugreifen

Innere Klassen können auf alle Member der äußeren Klasse zugreifen – sogar auf private Felder und Methoden.

class Encryption {
    private final String secretKey = "s3cr3t"; // private!

    class Encryptor {
        String encrypt(String data) {
            // Inner class accesses private outer field
            return data + "|" + secretKey.hashCode();
        }
    }

    class Decryptor {
        String decrypt(String encrypted) {
            int idx = encrypted.lastIndexOf('|');
            return encrypted.substring(0, idx);
        }
    }
}

Überschattung mit this

Wenn eine innere Klasse ein Feld mit demselben Namen wie die äußere Klasse besitzt, verwenden Sie OuterClass.this.field, um auf das äußere Feld zu verweisen.

class Outer {
    int value = 10;

    class Inner {
        int value = 20; // shadows outer.value

        void printBoth() {
            System.out.println("Inner value: " + value);         // 20
            System.out.println("Outer value: " + Outer.this.value); // 10
        }
    }
}

new Outer().new Inner().printBoth();
// Inner value: 20
// Outer value: 10

Iterator-Muster mit innerer Klasse

Ein klassischer Anwendungsfall: die Implementierung eines Iterators als innere Klasse, die auf die privaten Daten der umgebenden Collection zugreift.

class NumberRange implements Iterable<Integer> {
    private final int start;
    private final int end;

    NumberRange(int start, int end) {
        this.start = start; this.end = end;
    }

    @Override
    public java.util.Iterator<Integer> iterator() {
        return new RangeIterator(); // inner class instance
    }

    private class RangeIterator implements java.util.Iterator<Integer> {
        private int current = start; // accesses outer start

        public boolean hasNext() { return current <= end; }
        public Integer next()    { return current++; }
    }
}

for (int n : new NumberRange(1, 5)) System.out.print(n + " ");
// 1 2 3 4 5

Event-Listener als innere Klassen

GUI- und ereignisgesteuerte Programmierung verwendet häufig innere Klassen, um Event-Listener zu implementieren, die auf den Zustand der umgebenden UI-Komponente zugreifen können.

// Swing-style example (conceptual)
class LoginPanel {
    private String username = "";

    class LoginButtonListener {
        void onButtonClicked() {
            if (username.isEmpty()) {
                System.out.println("Please enter username"); // accesses outer field
            } else {
                System.out.println("Logging in as: " + username);
            }
        }
    }

    void setUsername(String name) { this.username = name; }
}
LoginPanel panel = new LoginPanel();
panel.setUsername("alice");
panel.new LoginButtonListener().onButtonClicked();
// Logging in as: alice

Innere Klassen in Collections

Einige Collection-Implementierungen verwenden innere Klassen, um Cursor oder Sichten zu kapseln, die von der umgebenden Collection unterstützt werden.

class SimpleStack<T> {
    private Object[] elements;
    private int size = 0;

    SimpleStack(int capacity) {
        elements = new Object[capacity];
    }

    void push(T item) {
        if (size >= elements.length) throw new StackOverflowError();
        elements[size++] = item;
    }

    T pop() {
        if (size == 0) throw new java.util.EmptyStackException();
        T item = (T) elements[--size];
        elements[size] = null;
        return item;
    }

    int size() { return size; }
}

Warnung vor Speicherlecks

Instanzen innerer Klassen enthalten eine Referenz auf die äußere Instanz. Wenn die innere Klasse aus der äußeren Klasse entweicht (z. B. in einer langlebigen Collection gespeichert wird), kann die äußere Instanz nicht durch Garbage Collection freigegeben werden.

// Memory leak: anonymous inner class (implicit outer ref) stored statically
class LeakExample {
    byte[] data = new byte[1024 * 1024]; // 1MB

    // BAD: this Runnable holds a reference to LeakExample.this
    Runnable leak = new Runnable() {
        public void run() { System.out.println(data.length); }
    };
}
// If 'leak' is stored somewhere, LeakExample (and its 1MB) is never GC'd

// FIX: use a static nested class or a lambda that captures only needed values
static Runnable noLeak(byte[] data) {
    return () -> System.out.println(data.length); // captures array, not outer
}

Vergleich: Innere Klasse vs. Lambda

Moderne Java-Lambdas ersetzen häufig anonyme innere Klassen für Interfaces mit nur einer Methode. Lambdas sind kompakter, verfügen aber NICHT über ein eigenes this.

// Old way: anonymous inner class
Runnable r1 = new Runnable() {
    @Override
    public void run() {
        System.out.println("Running (inner class) — this is the Runnable");
    }
};

// Modern: lambda
Runnable r2 = () -> System.out.println("Running (lambda)");

r1.run();
r2.run();

// Lambda this = enclosing class (not the Runnable)
// Inner class this = the Runnable instance itself

Wann innere Klassen verwendet werden

Verwenden Sie nicht statische innere Klassen, wenn:

  • Die Klasse auf den privaten Zustand der umgebenden Instanz zugreifen muss
  • Jede innere Instanz logisch an eine bestimmte äußere Instanz gebunden ist
  • Sie das Iterator-Muster zur Kapselung der Traversierungslogik verwenden

Praxis: Paginator

Ein praxisnaher Paginator, bei dem die innere Klasse den Seitenstatus speichert und auf die Datenliste der äußeren Klasse zugreift.

import java.util.*;

class Paginator<T> {
    private final List<T> items;
    private final int pageSize;

    Paginator(List<T> items, int pageSize) {
        this.items = items; this.pageSize = pageSize;
    }

    class Page {
        private int pageIndex = 0;

        List<T> current() {
            int start = pageIndex * pageSize;
            int end = Math.min(start + pageSize, items.size()); // outer
            return start < items.size() ? items.subList(start, end) : List.of();
        }
        boolean hasNext() { return (pageIndex + 1) * pageSize < items.size(); }
        void next() { if (hasNext()) pageIndex++; }
    }
}
Paginator<String> p = new Paginator<>(List.of("a","b","c","d","e"), 2);
Paginator.Page page = p.new Page();
System.out.println(page.current()); // [a, b]
page.next();
System.out.println(page.current()); // [c, d]

Kurztest

Was speichert eine innere (nicht statische) Klasse, das eine statisch geschachtelte Klasse nicht speichert?

Zusammenfassung: Innere Klassen und Zugriff auf die äußere Klasse

Die wichtigsten Erkenntnisse:

  • Nicht statische innere Klassen enthalten implizit eine Referenz auf die einschließende Instanz der äußeren Klasse
  • Erzeugen Sie Instanzen innerer Klassen nur über eine Instanz der äußeren Klasse: outer.new Inner()
  • Innere Klassen können auf alle Member der äußeren Klasse zugreifen, einschließlich privater Felder
  • Verwenden Sie Outer.this.field, um gleichnamige Felder eindeutig anzusprechen
  • Geeignete Einsatzgebiete: Iteratoren, Event-Listener und innere Datenstrukturen
  • Risiko: Instanzen innerer Klassen verhindern, dass Instanzen der äußeren Klasse durch die Garbage Collection freigegeben werden
Kostenlos starten

Lerne Java mit einem KI-Tutor — kostenlos

Schreibe und führe echten Code in deinem Browser aus, bekomme sofortige Hilfe von einem 24/7 KI-Tutor und setze dein Lernen im Web oder in der App fort.

Kurse
104
Lektionen
374

Häufig gestellte Fragen

Ist die Lektion „Innere Klassen und Zugriff auf die äußere Klasse“ kostenlos?

Ja — der vollständige Text von „Innere Klassen und Zugriff auf die äußere Klasse“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Java Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Java Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Innere Klassen und Zugriff auf die äußere Klasse“?

Verwenden Sie nicht statische innere Klassen, die eine Referenz auf die Instanz der äußeren Klasse halten. Du übst Java Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Java Academy zu starten?

Keine Vorkenntnisse erforderlich. Java Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 2 von 4.

Wie lange dauert die Lektion „Innere Klassen und Zugriff auf die äußere Klasse“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Java Academy-Lektion Code schreiben und ausführen?

Ja. Jede Java Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Statische verschachtelte Klassen
  2. Innere Klassen und Zugriff auf die äußere Klasse
  3. Lokale und anonyme Klassen
  4. Die passende Verschachtelungsstrategie wählen
← Zurück zu Java Academy