Innere Klassen (Inner Classes)
Java erlaubt es, Klassen und Schnittstellen zu verschachteln. Ziel innerer Klassen ist es, Hilfsklassen möglichst nah an der Stelle zu definieren, wo sie benötigt werden — z.B. Ausnahmeklassen, Komparatoren oder Ereignisbehandler. Alle bisher bekannten Klassen, die auf der obersten Ebene definiert sind, nennt man auch äußere Klassen oder Top-Level-Klassen.
Geschachtelte Klassen (Nested Classes)
Geschachtelte Klassen sind statische Top-Level-Klassen, die innerhalb einer anderen Top-Level-Klasse zur Strukturierung des Namensraums definiert werden. Da sie statisch sein müssen, sind sie im eigentlichen Sinne keine echten inneren Klassen.
- Geschachtelte Klasse
- Startklasse
public abstract class Computer {
...
public static final class Notebook extends Computer implements Comparable<Notebook> {...}
public static final class Cpu {...}
...
}
public class MainClass {
public static void main(String[] args) {
Computer.Cpu cpu = new Computer.Cpu(4.7, 8);
Computer.Notebook notebook = new Computer.Notebook("Mein Gaming Laptop", cpu, 32, 16);
}
}
Elementklassen (Member Classes)
Objekte von Elementklassen sind immer an ein Objekt der umgebenden Klasse gebunden. Das ermöglicht die Umsetzung von Kompositionen (siehe Darstellung von Assoziationen). Elementklassen haben Zugriff auf alle Variablen und Methoden der umgebenden Klasse, dürfen aber keine statischen Elemente enthalten.
- Elementklasse
- Startklasse
public class List {
...
public class Item {...}
...
}
public class MainClass {
public static void main(String[] args) {
List list = new List();
List.Item item = new List.Item(); // Kompilierungsfehler: Elementklasse benötigt umgebendes Objekt
List.Item item = list.new Item(); // korrekt
}
}
Lokale Klassen
Lokale Klassen werden innerhalb einer Methode definiert und sind auch nur dort
verwendbar. Sie dürfen nicht als public, protected, private oder static
deklariert werden, dürfen keine statischen Elemente enthalten und können nur auf
final-markierte Variablen und Parameter der umgebenden Methode zugreifen.
- Schnittstelle
- Verwenderklasse
- Startklasse mit lokaler Klasse
public interface Translator {
String translate(String s);
}
public class Computers {
public static String translateDescription(Computer computer, Translator translator) {
return translator.translate(computer.getDescription());
}
}
public class MainClass {
public static void main(String[] args) throws InvalidValueException {
class ToUpperCaseTranslator implements Translator {
@Override
public String translate(String s) {
return s.toUpperCase();
}
}
ToUpperCaseTranslator translator = new ToUpperCaseTranslator();
Computer computer = new Notebook("Mein Gaming Laptop", new Cpu(4.7, 8), 32, 16);
String description = Computers.translateDescription(computer, translator);
System.out.println(description);
}
}
Anonyme Klassen
Anonyme Klassen haben im Gegensatz zu lokalen Klassen keinen Namen. Sie werden direkt innerhalb eines Ausdrucks definiert und instanziiert — Klassendeklaration und Objekterzeugung sind also in einem Konstrukt vereint. Ist der erwartete Datentyp eine Schnittstelle, implementiert die anonyme Klasse diese; ist es eine Klasse, wird daraus abgeleitet.
- Schnittstelle
- Verwenderklasse
- Startklasse mit anonymer Klasse
public interface Translator {
String translate(String s);
}
public class Computers {
public static String translateDescription(Computer computer, Translator translator) {
return translator.translate(computer.getDescription());
}
}
public class MainClass {
public static void main(String[] args) throws InvalidValueException {
Computer computer = new Notebook("Mein Gaming Laptop", new Cpu(4.7, 8), 32, 16);
String description = Computers.translateDescription(computer, new Translator() {
@Override
public String translate(String s) {
return s.toUpperCase();
}
});
System.out.println(description);
}
}