Viele Menschen sind möglicherweise nicht mit den inneren Klassen von Java vertraut. Tatsächlich gibt es in C++ ein ähnliches Konzept, nämlich verschachtelte Klassen. Die Unterschiede und Verbindungen zwischen den beiden werden im Folgenden verglichen. Oberflächlich betrachtet ist eine innere Klasse nur eine weitere innerhalb der Klasse definierte Klasse (wie Sie unten sehen werden, können innere Klassen an vielen Stellen definiert werden), aber tatsächlich ist es nicht so einfach. Auf den ersten Blick scheinen innere Klassen etwas zu sein Überflüssig Der Nutzen ist für Anfänger vielleicht nicht so offensichtlich, aber mit einem tieferen Verständnis werden Sie feststellen, dass die Designer von Java mit internen Klassen gute Absichten haben. Das Erlernen der Verwendung innerer Klassen ist Teil der Beherrschung der fortgeschrittenen Java-Programmierung, wodurch Sie Ihre Programmstruktur eleganter gestalten können. Lassen Sie uns es unter folgenden Aspekten vorstellen:
erstes Treffen
Kopieren Sie den Codecode wie folgt:
öffentliche Schnittstelle Inhalt {
int value();
}
öffentliche Schnittstelle Ziel {
String readLabel();
}
öffentliche Klasse Güter {
private Klasse Content implementiert Contents {
private int i = 11;
public int value() {
gib i zurück;
}
}
Die geschützte Klasse GDestination implementiert Destination {
privates String-Label;
private GDestination(String whereTo) {
label = wohin;
}
öffentlicher String readLabel() {
Rücksendeetikett;
}
}
öffentliches Ziel dest(String s) {
neue GDestination(s) zurückgeben;
}
öffentliche Inhalte cont() {
return new Content();
}
}
Klasse TestGoods {
public static void main(String[] args) {
Waren p = neue Waren();
Inhalt c = p.cont();
Ziel d = p.dest("Peking");
}
}
In diesem Beispiel sind die Klassen Content und GDestination innerhalb der Klasse Goods definiert und verfügen über protected bzw. private Modifikatoren zur Steuerung der Zugriffsebenen. Der Inhalt stellt den Inhalt der Waren dar, und GDestination stellt den Bestimmungsort der Waren dar. Sie implementieren jeweils zwei Schnittstellen Content und Destination. In der folgenden Hauptmethode verwenden Sie direkt Contents c und Destination d, um zu operieren. Sie sehen nicht einmal die Namen dieser beiden internen Klassen! Auf diese Weise besteht der erste Vorteil innerer Klassen darin, Vorgänge zu verbergen, von denen Sie nicht möchten, dass andere sie kennen, nämlich die Kapselung.
Gleichzeitig haben wir auch die erste Möglichkeit entdeckt, ein Objekt der inneren Klasse außerhalb des Geltungsbereichs der äußeren Klasse zu erhalten, nämlich es mithilfe der Methoden seiner äußeren Klasse zu erstellen und zurückzugeben. Dies geschieht mit den Methoden cont() und dest() im obigen Beispiel. Gibt es also eine andere Möglichkeit?
Natürlich gibt es das,
das Syntaxformat ist wie folgt:
äußeresObjekt=neue äußereKlasse(Konstruktorparameter);
äußereKlasse.innerKlasse innerObject=outerObject.new InnerClass(Konstruktorparameter);
Beachten Sie, dass Sie beim Erstellen eines nicht statischen inneren Klassenobjekts zuerst das entsprechende äußere Klassenobjekt erstellen müssen. Was den Grund betrifft, führt dies zu unserem nächsten Thema. Nicht-statische innere Klassenobjekte haben Verweise auf ihre
äußeren Klassenobjekte.
Kopieren Sie den Codecode wie folgt:
öffentliche Klasse Güter {
private int valueRate = 2;
private Klasse Content implementiert Contents {
private int i = 11 * valueRate;
public int value() {
gib i zurück;
}
}
Die geschützte Klasse GDestination implementiert Destination {
privates String-Label;
private GDestination(String whereTo) {
label = wohin;
}
öffentlicher String readLabel() {
Rücksendeetikett;
}
}
öffentliches Ziel dest(String s) {
neue GDestination(s) zurückgeben;
}
öffentliche Inhalte cont() {
return new Content();
}
}
Hier fügen wir der Goods-Klasse eine private Mitgliedsvariable hinzu, die den Wertkoeffizienten der Ware darstellt. Sie wird damit multipliziert, wenn die value()-Methode der internen Klasse Content den Wert berechnet. Wir haben festgestellt, dass value() auf valueRate zugreifen kann, was den zweiten Vorteil innerer Klassen darstellt. Ein inneres Klassenobjekt kann auf den Inhalt des äußeren Klassenobjekts zugreifen, das es erstellt hat, sogar auf private Variablen! Dies ist eine sehr nützliche Funktion, die uns beim Entwerfen mehr Ideen und Verknüpfungen bietet. Um diese Funktion zu erreichen, muss das innere Klassenobjekt einen Verweis auf das äußere Klassenobjekt haben. Wenn der Java-Compiler ein inneres Klassenobjekt erstellt, übergibt er implizit die Referenz an sein äußeres Klassenobjekt und behält sie bei. Dadurch kann das innere Klassenobjekt immer auf sein äußeres Klassenobjekt zugreifen. Aus diesem Grund müssen Sie zum Erstellen eines inneren Klassenobjekts außerhalb des Gültigkeitsbereichs der äußeren Klasse zuerst dessen äußeres Klassenobjekt erstellen.
Einige Leute fragen sich vielleicht: Was soll ich tun, wenn eine Mitgliedsvariable in der inneren Klasse denselben Namen hat wie eine Mitgliedsvariable in der äußeren Klasse, das heißt, die Mitgliedsvariable der äußeren Klasse mit demselben Namen ist blockiert? Es ist in Ordnung, dass Java das folgende Format verwendet, um Verweise auf externe Klassen auszudrücken:
äußereKlasse.this
Damit haben wir keine Angst vor dieser Abschirmungssituation.
statische innere Klasse
Wie gewöhnliche Klassen können auch innere Klassen statisch sein. Der Unterschied zu nicht statischen inneren Klassen besteht jedoch darin, dass statische innere Klassen keine externen Referenzen haben. Dies ist tatsächlich den verschachtelten Klassen in C++ sehr ähnlich. Der größte Unterschied zwischen internen Java-Klassen und verschachtelten C++-Klassen besteht natürlich darin, ob es aus gestalterischer Sicht und in einigen Details einen Unterschied gibt.
Darüber hinaus darf es in keiner nicht statischen inneren Klasse statische Daten, statische Methoden oder andere statische innere Klassen geben (innere Klassen können auf mehr als einer Ebene verschachtelt sein). Aber Sie können all dies in statischen inneren Klassen haben. Dies kann als zweiter Unterschied zwischen den beiden angesehen werden.
lokale innere Klasse
Ja, innere Java-Klassen können auch lokal sein, sie können innerhalb einer Methode oder sogar eines Codeblocks definiert werden.
Kopieren Sie den Codecode wie folgt:
öffentliche Klasse Goods1 {
öffentliches Ziel dest(String s) {
Klasse GDestination implementiert Destination {
privates String-Label;
private GDestination(String whereTo) {
label = wohin;
}
öffentlicher String readLabel() {
Rücksendeetikett;
}
}
neue GDestination(s) zurückgeben;
}
public static void main(String[] args) {
Ware1 g = neue Ware1();
Ziel d = g.dest("Beijing");
}
}
Das Obige ist ein solches Beispiel. In der Methode dest definieren wir eine innere Klasse, und schließlich gibt diese Methode das Objekt dieser inneren Klasse zurück. Wenn wir nur ein Objekt einer inneren Klasse erstellen und es nach außen erzeugen müssen, können wir dies tun. Natürlich können in Methoden definierte innere Klassen das Design diversifizieren, und ihre Verwendung ist nicht darauf beschränkt.
Hier ist ein noch seltsameres Beispiel:
Kopieren Sie den Codecode wie folgt:
öffentliche Klasse Goods2 {
private void internalTracking(boolean b) {
wenn (b) {
Klasse TrackingSlip {
private String-ID;
TrackingSlip(String s) {
id = s;
}
String getSlip() {
Rückgabe-ID;
}
}
TrackingSlip ts = new TrackingSlip("slip");
String s = ts.getSlip();
}
}
public void track() {
internalTracking(true);
}
public static void main(String[] args) {
Waren2 g = neue Waren2();
g.track();
}
}
Sie können kein Objekt dieser inneren Klasse außerhalb von if erstellen, da es über seinen Gültigkeitsbereich hinausgeht. Während der Kompilierung wird die interne Klasse TrackingSlip jedoch gleichzeitig mit anderen Klassen kompiliert, mit der Ausnahme, dass sie über einen eigenen Bereich verfügt und außerhalb dieses Bereichs ungültig ist. Ansonsten unterscheidet sie sich nicht von anderen internen Klassen.
anonyme innere Klasse
Die Syntaxregeln der anonymen inneren Klassen von Java mögen etwas seltsam erscheinen, aber wenn Sie wie bei anonymen Arrays nur ein Objekt einer Klasse erstellen müssen und ihren Namen nicht benötigen, kann die Verwendung innerer Klassen dazu führen, dass der Code prägnant und klar aussieht. Seine Syntaxregeln lauten wie folgt:
neuer Schnittstellenname(){......}; oder neuer Superklassenname(){......};
Fahren wir mit dem folgenden Beispiel fort:
Kopieren Sie den Codecode wie folgt:
öffentliche Klasse Goods3 {
öffentliche Inhalte cont() {
return new Contents() {
private int i = 11;
public int value() {
gib i zurück;
}
};
}
}
Die Methode cont() verwendet hier eine anonyme innere Klasse, um direkt ein Objekt einer Klasse zurückzugeben, die die Contents-Schnittstelle implementiert, was in der Tat sehr einfach aussieht.
In anonymen Adaptern für die Java-Ereignisverarbeitung werden häufig anonyme innere Klassen verwendet. Wenn Sie beispielsweise das Fenster schließen möchten, fügen Sie diesen Code hinzu:
Kopieren Sie den Codecode wie folgt:
frame.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
Zu beachten ist, dass die anonyme innere Klasse keinen Namen und keinen Konstruktor hat (wenn die anonyme innere Klasse jedoch eine übergeordnete Klasse erbt, die nur einen parametrisierten Konstruktor enthält, muss sie diese Parameter beim Erstellen mitbringen und Super verwenden). Schlüsselwort, um den entsprechenden Inhalt während des Implementierungsprozesses aufzurufen). Wenn Sie seine Mitgliedsvariablen initialisieren möchten, gibt es mehrere Methoden:
Wenn es sich um eine anonyme innere Klasse einer Methode handelt, können Sie diese Methode verwenden, um die gewünschten Parameter zu übergeben. Beachten Sie jedoch, dass diese Parameter als endgültig deklariert werden müssen.
Transformieren Sie die anonyme innere Klasse in eine benannte lokale innere Klasse, damit sie einen Konstruktor haben kann.
Verwenden Sie in dieser anonymen inneren Klasse einen Initialisierungsblock.
Warum brauchen Sie innere Klassen?
Was sind die Vorteile von inneren Java-Klassen? Warum brauchen Sie innere Klassen?
Nehmen wir zunächst ein einfaches Beispiel. Wenn Sie eine Schnittstelle implementieren möchten, eine Methode in dieser Schnittstelle jedoch denselben Namen und dieselben Parameter wie eine Methode in der von Ihnen konzipierten Klasse hat, was sollten Sie tun? Zu diesem Zeitpunkt können Sie eine innere Klasse erstellen, um diese Schnittstelle zu implementieren. Da auf die innere Klasse alles in der äußeren Klasse zugreifen kann, stehen Ihnen auf diese Weise alle Funktionen zur Verfügung, die Sie hätten, wenn Sie die Schnittstelle direkt implementieren würden.
Aber Sie fragen sich vielleicht: Wäre es nicht ausreichend, nur die Methode zu ändern?
Tatsächlich ist es nicht wirklich überzeugend, dies als Grund für die Gestaltung interner Klassen zu verwenden.
Der wahre Grund ist folgender: Gemeinsam können die internen Klassen und Schnittstellen in Java ein Problem lösen, über das sich C++-Programmierer in Java oft beschweren, ohne dass es eine Mehrfachvererbung gibt. Tatsächlich ist die Mehrfachvererbung von C++ sehr kompliziert zu entwerfen, und Java kann den Effekt der Mehrfachvererbung sehr gut durch interne Klassen und Schnittstellen erzielen.