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.
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.0Auf 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: 10Iterator-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 5Event-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: aliceInnere 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 itselfWann 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
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
- Statische verschachtelte Klassen
- Innere Klassen und Zugriff auf die äußere Klasse
- Lokale und anonyme Klassen
- Die passende Verschachtelungsstrategie wählen