Was ist der Hauptunterschied zwischen einer inneren Klasse und einer statischen verschachtelten Klasse in Java? Spielt der Entwurf/die Implementierung eine Rolle bei der Wahl einer dieser beiden Klassen?
Antworten
Zu viele Anzeigen?Einfach ausgedrückt, brauchen wir verschachtelte Klassen vor allem deshalb, weil Java keine Abschlüsse bietet.
Verschachtelte Klassen sind Klassen, die innerhalb des Körpers einer anderen Klasse definiert sind. Es gibt zwei Arten von Klassen - statische und nicht statische.
Sie werden als Mitglieder der umschließenden Klasse behandelt, daher können Sie jeden der vier Zugriffsspezifizierer angeben - private, package, protected, public
. Diesen Luxus haben wir bei Top-Level-Klassen nicht, die nur deklariert werden können public
oder paket-privat.
Innere Klassen, auch bekannt als Nicht-Stapel-Klassen, haben Zugriff auf andere Mitglieder der oberen Klasse, auch wenn sie als privat deklariert sind, während statische verschachtelte Klassen keinen Zugriff auf andere Mitglieder der oberen Klasse haben.
public class OuterClass {
public static class Inner1 {
}
public class Inner2 {
}
}
Inner1
ist unsere statische innere Klasse und Inner2
ist unsere innere Klasse, die nicht statisch ist. Der Hauptunterschied zwischen ihnen besteht darin, dass man keine statische Klasse erstellen kann. Inner2
Instanz ohne ein Outer, während Sie eine Inner1
Objekt unabhängig.
Wann würden Sie die innere Klasse verwenden?
Stellen Sie sich eine Situation vor, in der Class A
y Class B
verwandt sind, Class B
muss zugreifen Class A
Mitglieder, und Class B
bezieht sich nur auf Class A
. Hier kommt der innere Unterricht ins Spiel.
Um eine Instanz der inneren Klasse zu erstellen, müssen Sie eine Instanz Ihrer äußeren Klasse erstellen.
OuterClass outer = new OuterClass();
OuterClass.Inner2 inner = outer.new Inner2();
o
OuterClass.Inner2 inner = new OuterClass().new Inner2();
Wann würden Sie die statische innere Klasse verwenden?
Sie würden eine statische innere Klasse definieren, wenn Sie wissen, dass sie keine Beziehung zu der Instanz der umschließenden Klasse/Topklasse hat. Wenn Ihre innere Klasse keine Methoden oder Felder der äußeren Klasse verwendet, ist sie nur eine Platzverschwendung, also machen Sie sie statisch.
Um zum Beispiel ein Objekt für die statische verschachtelte Klasse zu erstellen, verwenden Sie diese Syntax:
OuterClass.Inner1 nestedObject = new OuterClass.Inner1();
Der Vorteil einer statischen verschachtelten Klasse ist, dass sie kein Objekt der enthaltenden Klasse/Top-Klasse benötigt, um zu funktionieren. Dies kann Ihnen helfen, die Anzahl der Objekte zu reduzieren, die Ihre Anwendung zur Laufzeit erzeugt.
Ich denke, dass die Konvention, die im Allgemeinen befolgt wird, die folgende ist:
- statische Klasse innerhalb einer Klasse der obersten Ebene ist eine verschachtelte Klasse
- nicht statische Klasse innerhalb einer Klasse der obersten Ebene ist eine innere Klasse , die außerdem zwei weitere Formen hat:
- lokale Klasse - benannte Klassen, die innerhalb eines Blocks wie einem Methoden- oder Konstruktorkörper deklariert werden
- anonyme Klasse - unbenannte Klassen, deren Instanzen in Ausdrücken und Anweisungen erzeugt werden
Allerdings sind nur wenige andere weist auf Erinnerungen hin sind:
-
Klassen der obersten Ebene und statische verschachtelte Klassen sind semantisch gleich, mit der Ausnahme, dass eine statische verschachtelte Klasse einen statischen Verweis auf private statische Felder/Methoden ihrer äußeren [übergeordneten] Klasse herstellen kann und umgekehrt.
-
Innere Klassen haben Zugriff auf Instanzvariablen der umschließenden Instanz der Äußeren [Eltern-]Klasse. Allerdings haben nicht alle inneren Klassen umschließende Instanzen, zum Beispiel innere Klassen in statischen Kontexten, wie eine anonyme Klasse, die in einem statischen Initialisierungsblock verwendet wird, nicht.
-
Eine anonyme Klasse erweitert standardmäßig die übergeordnete Klasse oder implementiert die übergeordnete Schnittstelle, und es gibt keine weitere Klausel zur Erweiterung einer anderen Klasse oder zur Implementierung weiterer Schnittstellen. Also,
new YourClass(){};
bedeutetclass [Anonymous] extends YourClass {}
new YourInterface(){};
bedeutetclass [Anonymous] implements YourInterface {}
Meines Erachtens bleibt die große Frage offen, welches Mittel wann eingesetzt werden soll. Nun, das hängt vor allem davon ab, mit welchem Szenario Sie zu tun haben, aber das Lesen der Antwort von @jrudolph kann Ihnen bei der Entscheidungsfindung helfen.
Verschachtelte Klasse: Klasse in Klasse
Typen:
- Statische verschachtelte Klasse
- Nicht-statische verschachtelte Klasse [Innere Klasse]
Der Unterschied:
Nicht-statische verschachtelte Klasse [Innere Klasse]
In nicht statischen verschachtelten Klassen existieren Objekte der inneren Klasse innerhalb von Objekten der äußeren Klasse. Somit ist das Datenelement der äußeren Klasse für die innere Klasse zugänglich. Um also ein Objekt der inneren Klasse zu erstellen, müssen wir zuerst ein Objekt der äußeren Klasse erstellen.
outerclass outerobject=new outerobject();
outerclass.innerclass innerobjcet=outerobject.new innerclass();
Statische verschachtelte Klasse
In statischen verschachtelten Klassen braucht das Objekt der inneren Klasse kein Objekt der äußeren Klasse, da das Wort "statisch" darauf hinweist, dass kein Objekt erstellt werden muss.
class outerclass A {
static class nestedclass B {
static int x = 10;
}
}
Wenn Sie auf x zugreifen wollen, dann schreiben Sie innerhalb der Methode Folgendes
outerclass.nestedclass.x; i.e. System.out.prinltn( outerclass.nestedclass.x);
Die Instanz der inneren Klasse wird erstellt, wenn die Instanz der äußeren Klasse erstellt wird. Daher haben die Mitglieder und Methoden der inneren Klasse Zugriff auf die Mitglieder und Methoden der Instanz (des Objekts) der äußeren Klasse. Wenn die Instanz der äußeren Klasse den Anwendungsbereich verlässt, hören auch die Instanzen der inneren Klasse auf zu existieren.
Die statische verschachtelte Klasse hat keine konkrete Instanz. Sie wird nur geladen, wenn sie zum ersten Mal verwendet wird (genau wie die statischen Methoden). Sie ist eine völlig unabhängige Einheit, deren Methoden und Variablen keinen Zugriff auf die Instanzen der äußeren Klasse haben.
Die statischen verschachtelten Klassen sind nicht mit dem äußeren Objekt gekoppelt, sie sind schneller und benötigen keinen Heap-/Stapelspeicher, da es nicht notwendig ist, eine Instanz einer solchen Klasse zu erstellen. Als Faustregel gilt daher, dass man versuchen sollte, statische verschachtelte Klassen mit einem möglichst begrenzten Anwendungsbereich zu definieren (private >= class >= protected >= public) und sie dann in eine innere Klasse umzuwandeln (indem man den Bezeichner "static" entfernt) und den Anwendungsbereich zu lockern, wenn dies wirklich notwendig ist.
Die Verwendung verschachtelter statischer Klassen birgt eine Feinheit in sich, die in bestimmten Situationen nützlich sein kann.
Statische Attribute hingegen werden instanziiert, bevor die Klasse über ihren Konstruktor instanziiert wird, werden statische Attribute innerhalb von verschachtelten statischen Klassen anscheinend erst instanziiert, nachdem die Konstruktor der Klasse aufgerufen wird, oder zumindest nicht, bevor die Attribute zum ersten Mal referenziert werden, selbst wenn sie als 'final' markiert sind.
Betrachten Sie dieses Beispiel:
public class C0 {
static C0 instance = null;
// Uncomment the following line and a null pointer exception will be
// generated before anything gets printed.
//public static final String outerItem = instance.makeString(98.6);
public C0() {
instance = this;
}
public String makeString(int i) {
return ((new Integer(i)).toString());
}
public String makeString(double d) {
return ((new Double(d)).toString());
}
public static final class nested {
public static final String innerItem = instance.makeString(42);
}
static public void main(String[] argv) {
System.out.println("start");
// Comment out this line and a null pointer exception will be
// generated after "start" prints and before the following
// try/catch block even gets entered.
new C0();
try {
System.out.println("retrieve item: " + nested.innerItem);
}
catch (Exception e) {
System.out.println("failed to retrieve item: " + e.toString());
}
System.out.println("finish");
}
}
Obwohl "nested" und "innerItem" beide als "static final" deklariert sind, wird die Einstellung von nested.innerItem erst nach der Instanziierung der Klasse (oder zumindest erst nachdem das verschachtelte statische Element zum ersten Mal referenziert wird), wie Sie selbst sehen können indem Sie die Zeilen, auf die ich mich oben beziehe, auskommentieren und auskommentieren. Das Gleiche gilt nicht gilt nicht für 'outerItem'.
Zumindest ist es das, was ich in Java 6.0 sehe.
99 Stimmen
Die Antwort von Joshua Bloch ist in Leistungsfähiges Java lesen
item 22 : Favor static member classes over non static
24 Stimmen
Für das Protokoll, es ist Punkt 24 in der 3. Auflage des gleichen Buches.