Innere Klassen (Inner Classes)
Java bietet die Möglichkeit, Klassen und Schnittstellen zu verschachteln. Das Ziel von inneren Klassen ist eine Definition von Hilfsklassen möglichst nahe an der Stelle, wo sie gebraucht werden. Beispiele für Hilfsklassen sind Ausnahmeklassen, Komparatoren und Ereignisbehandler. Alle bisherigen Klassen werden auch als äußerer Klassen bzw. Top-Level-Klassen bezeichnet.
Geschachtelte Klassen (Nested Classes)
Geschachtelte Klassen sind Top-Level-Klassen, die zur Strukturierung des
Namensraumes in anderen Top-Level-Klassen definiert sind. Ein Namensraum ist die
vollständige Pfadangabe zur Klasse (z.B. java.lang
). Geschachtelte Klassen
müssen statisch definiert werden und sind daher im eigentlichen Sinne keine
richtigen 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 mit einem Objekt der umgebenden Klasse verbunden. Dies ermöglicht die Umsetzung von Kompositionen (siehe Darstellung von Assoziationen). Sie haben Zugriff auf alle Variablen und Methoden der sie umgebenden Klasse und dürfen 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
List.Item item = list.new Item();
}
}
Lokale Klassen
Lokale Klassen werden innerhalb einer Methode definiert und können auch nur dort
verwendet werden. Sie dürfen nicht als public
, protected
, private
oder
static
definiert werden, dürfen keine statischen Elemente enthalten und können
nur die mit final
markierten Variablen und Parameter der umgebenden Methode
verwenden.
- 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 besitzen im Gegensatz zu lokalen Klassen keinen Namen und werden innerhalb eines Ausdrucks definiert und instanziiert; Klassendeklaration und Objekterzeugung sind also in einem Sprachkonstrukt vereint. Wird als Datentyp eine Schnittstelle benötigt, implementiert die anonyme Klasse diese Schnittstelle, wird als Datentyp eine Klasse benötigt, so wird die anonyme Klasse 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);
}
}