Innere, geschachtelte & anonyme Klassen
Teil des Abschnitts Objektorientierte Programmierung der Java-Journey von Coddy — Lektion 49 von 87.
Java ermöglicht es Ihnen, Klassen innerhalb anderer Klassen zu definieren. Diese inneren Klassen helfen dabei, Code zu organisieren, indem sie verwandte Funktionalitäten gruppieren, und können direkt auf die Member der äußeren Klasse zugreifen.
Eine geschachtelte innere Klasse ist als Mitglied einer anderen Klasse definiert. Sie hat Zugriff auf alle Felder und Methoden der äußeren Klasse, einschließlich privater:
class Outer {
private String message = "Hello";
class Inner {
void display() {
System.out.println(message); // Kann auf privates Feld zugreifen
}
}
}
// Verwendung
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.display(); // Gibt aus: HelloEine lokale innere Klasse wird innerhalb einer Methode definiert. Sie kann nur innerhalb dieser Methode verwendet werden und kann auf lokale Variablen zugreifen, die effektiv final sind:
void process() {
String prefix = "Result: ";
class LocalHelper {
void print(int value) {
System.out.println(prefix + value);
}
}
new LocalHelper().print(42);
}Eine anonyme innere Klasse ist eine Klasse ohne Namen, die in einem einzigen Ausdruck erstellt und instanziiert wird. Sie wird häufig verwendet, um Schnittstellen zu implementieren oder Klassen spontan zu erweitern:
Comparator<String> comp = new Comparator<String>() {
@Override
public int compare(String a, String b) {
return a.length() - b.length();
}
};Innere Klassen sind besonders nützlich, wenn eine Klasse nur für eine andere Klasse relevant ist, wodurch Ihr Code organisiert und gekapselt bleibt.
Aufgabe
EinfachLassen Sie uns ein Warenkorbsystem bauen, das alle drei Arten von inneren Klassen demonstriert. Sie erstellen eine ShoppingCart-Klasse, die eine verschachtelte innere Klasse zur Darstellung von Artikeln, eine lokale innere Klasse zur Berechnung von Rabatten und eine anonyme innere Klasse zur Formatierung des endgültigen Belegs verwendet.
Sie organisieren Ihren Code in zwei Dateien:
ShoppingCart.java: Erstellen Sie die äußere Klasse, die ein Einkaufserlebnis verwaltet. Ihr ShoppingCart sollte ein privates FeldcustomerName(String) haben.Definieren Sie innerhalb von ShoppingCart eine verschachtelte innere Klasse namens
Itemmit zwei privaten Feldern:name(String) undprice(double). Geben Sie Item einen Konstruktor zur Initialisierung beider Felder und einegetDetails()-Methode, die Folgendes zurückgibt:[name]: $[price]Ihr ShoppingCart benötigt einen Konstruktor, der den Kundennamen entgegennimmt, und eine Methode namens
checkout(), die ein Item und einen Rabattprozentsatz (double) akzeptiert. Innerhalb voncheckout():- Erstellen Sie eine lokale innere Klasse namens
DiscountCalculatormit einer MethodeapplyDiscount(double originalPrice), die den Preis nach Anwendung des Rabattprozentsatzes zurückgibt. - Verwenden Sie die lokale Klasse, um den Endpreis zu berechnen.
- Erstellen Sie eine anonyme innere Klasse, die das
Formatter-Interface implementiert (dieses werden Sie definieren), um den Beleg zu formatieren. Die anonyme Klasse sollte eineformat()-Methode überschreiben, die einen mehrzeiligen Beleg-String zurückgibt.
Die
checkout()-Methode sollte den formatierten Beleg-String in genau diesem Format zurückgeben:--- Receipt --- Customer: [customerName] Item: [item details from getDetails()] Discount: [discount]% Final Price: $[calculated price]- Erstellen Sie eine lokale innere Klasse namens
Formatter.java: Definieren Sie ein einfaches Interface mit einer einzigen Methode:String format(). Dieses Interface wird von Ihrer anonymen inneren Klasse innerhalb der checkout-Methode implementiert.Main.java: Erwecken Sie Ihren Warenkorb zum Leben! Sie erhalten drei Eingaben: Kundenname (String), Artikelname (String) und Artikelpreis (double). Der Rabattprozentsatz ist auf10.0festgelegt.Erstellen Sie einen ShoppingCart mit dem Kundennamen. Erstellen Sie dann ein Item unter Verwendung der Syntax für äußere Klassenreferenzen:
cart.new Item(name, price). Rufen Siecheckout()mit dem Artikel und dem Rabatt auf und geben Sie den zurückgegebenen Beleg aus.
Sie erhalten drei Eingaben in der folgenden Reihenfolge: Kundenname, Artikelname und Artikelpreis.
Wenn die Eingaben beispielsweise Alice, Laptop und 1000.0 sind, beträgt der Endpreis nach einem Rabatt von 10 % 900.0.
Beachten Sie, wie jeder Typ der inneren Klasse einem anderen Zweck dient: Die verschachtelte Klasse gruppiert verwandte Daten mit der äußeren Klasse, die lokale Klasse kapselt Logik, die nur innerhalb einer Methode benötigt wird, und die anonyme Klasse bietet eine schnelle, einmalige Implementierung eines Interfaces!
Spickzettel
Java ermöglicht es Ihnen, Klassen innerhalb anderer Klassen zu definieren. Diese inneren Klassen helfen dabei, Code zu organisieren, indem sie zusammengehörige Funktionalitäten gruppieren, und können direkt auf die Elemente der äußeren Klasse zugreifen.
Verschachtelte innere Klasse
Eine verschachtelte innere Klasse wird als Element einer anderen Klasse definiert. Sie hat Zugriff auf alle Felder und Methoden der äußeren Klasse, einschließlich privater Elemente:
class Outer {
private String message = "Hello";
class Inner {
void display() {
System.out.println(message); // Kann auf privates Feld zugreifen
}
}
}
// Verwendung
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.display(); // Gibt aus: HelloLokale innere Klasse
Eine lokale innere Klasse wird innerhalb einer Methode definiert. Sie kann nur innerhalb dieser Methode verwendet werden und kann auf lokale Variablen zugreifen, die effektiv final sind:
void process() {
String prefix = "Result: ";
class LocalHelper {
void print(int value) {
System.out.println(prefix + value);
}
}
new LocalHelper().print(42);
}Anonyme innere Klasse
Eine anonyme innere Klasse ist eine Klasse ohne Namen, die in einem einzigen Ausdruck erstellt und instanziiert wird. Sie wird häufig verwendet, um Schnittstellen zu implementieren oder Klassen spontan zu erweitern:
Comparator<String> comp = new Comparator<String>() {
@Override
public int compare(String a, String b) {
return a.length() - b.length();
}
};Innere Klassen sind besonders nützlich, wenn eine Klasse nur für eine andere Klasse relevant ist, wodurch Ihr Code organisiert und gekapselt bleibt.
Probier es selbst
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Eingaben lesen
String customerName = scanner.nextLine();
String itemName = scanner.nextLine();
double itemPrice = scanner.nextDouble();
double discount = 10.0;
// TODO: Erstelle einen ShoppingCart mit dem Kundennamen
// TODO: Erstelle ein Item mit: cart.new Item(itemName, itemPrice)
// TODO: Rufe checkout() mit dem Item und dem Rabatt auf und gib das Ergebnis aus
}
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienEinführung in die OOPKlassen vs. ObjekteDas this-SchlüsselwortMethodenFelder (Attribute)Konstruktor-MethodeKonstruktor-ÜberladungRückblick – Einfacher Taschenrechner4Vererbung
Grundlagen der Vererbung (extends)Das super-SchlüsselwortMethoden überschreiben (@Override)Konstruktor-VerkettungDie Object-KlasseEinfache & mehrstufige VererbungWarum keine Mehrfachvererbung von KlassenZusammenfassung - Mitarbeiter-Hierarchie7Spezielle Methoden & Object-Klasse
toString()-Methodeequals() und hashCode()clone()-MethodecompareTo() und ComparableComparator-InterfaceZusammenfassung – Benutzerdefiniertes Sortieren2Zugriffsmodifikatoren & Kapselung
Überblick über ZugriffsebenenGetter- und Setter-MethodenInformation HidingDas final-SchlüsselwortRückblick – Bankkonto-Manager5Polymorphismus
Grundlagen der MethodenüberladungMethodenüberschreibung (Laufzeit)Upcasting und DowncastingDer instanceof-OperatorAbstrakte Klassen und MethodenZusammenfassung – Formenrechner8Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungAggregation vs. KompositionInnere, geschachtelte & anonyme KlassenEnums und Enum-MethodenRecords (Java 16+)Sealed Classes (Java 17+)11Design Patterns Teil 1
Einführung in Design PatternsSingleton-PatternFactory-PatternBuilder-PatternObserver-PatternStrategy-Pattern14Abschlussherausforderungen
E-Learning-PlattformBanksystemSpielcharakter-EntwicklungFahrzeugvermietung3Klasseneigenschaften & Statische Member
Instanz- vs. statische VariablenStatische MethodenStatische BlöckeKonstanten (static final)Zusammenfassung – Zähler & Utility6Interfaces & Abstrakte Klassen
Einführung in InterfacesInterfaces implementierenImplementierung mehrerer InterfacesDefault- & statische Methoden in InterfacesAbstrakte Klassen vs. InterfacesFunktionale InterfacesZusammenfassung - Zahlungssystem