Hier erstelle ich eine Instanz meiner Klasse
Nein, Sie erstellen hier nicht die Instanz Ihrer abstrakten Klasse. Sie erstellen vielmehr eine Instanz einer anonymen Unterklasse Ihrer abstrakten Klasse. Anschließend rufen Sie die Methode für Ihre abstrakte Klassenreferenz auf, die auf ein Unterklassenobjekt verweist .
Dieses Verhalten ist in JLS - Abschnitt 15.9.1 klar aufgeführt : -
Wenn der Ausdruck zur Erstellung der Klasseninstanz in einem Klassenkörper endet, ist die zu instanziierende Klasse eine anonyme Klasse. Dann:
- Wenn T eine Klasse bezeichnet, wird eine anonyme direkte Unterklasse der von T benannten Klasse deklariert. Es ist ein Fehler zur Kompilierungszeit, wenn die mit T bezeichnete Klasse eine endgültige Klasse ist.
- Wenn T eine Schnittstelle bezeichnet, wird eine anonyme direkte Unterklasse von Object deklariert, die die von T benannte Schnittstelle implementiert.
- In beiden Fällen ist der Hauptteil der Unterklasse der ClassBody, der im Ausdruck zur Erstellung der Klasseninstanz angegeben ist.
- Die zu instanziierende Klasse ist die anonyme Unterklasse.
Hervorhebung von mir.
In JLS - Abschnitt 12.5 können Sie außerdem Informationen zum Objekterstellungsprozess lesen . Ich werde hier eine Aussage daraus zitieren:
Jedes Mal, wenn eine neue Klasseninstanz erstellt wird, wird ihr Speicherplatz mit Platz für alle im Klassentyp deklarierten Instanzvariablen und alle in jeder Oberklasse des Klassentyps deklarierten Instanzvariablen zugewiesen, einschließlich aller möglicherweise ausgeblendeten Instanzvariablen.
Kurz bevor ein Verweis auf das neu erstellte Objekt als Ergebnis zurückgegeben wird, wird der angegebene Konstruktor verarbeitet, um das neue Objekt wie folgt zu initialisieren:
Den vollständigen Vorgang finden Sie unter dem von mir angegebenen Link.
Um praktisch zu sehen, dass die zu instanziierende Klasse eine anonyme Unterklasse ist , müssen Sie nur beide Klassen kompilieren. Angenommen, Sie legen diese Klassen in zwei verschiedenen Dateien ab:
My.java:
abstract class My {
public void myMethod() {
System.out.print("Abstract");
}
}
Poly.java:
class Poly extends My {
public static void main(String a[]) {
My m = new My() {};
m.myMethod();
}
}
Kompilieren Sie nun beide Quelldateien:
javac My.java Poly.java
In dem Verzeichnis, in dem Sie den Quellcode kompiliert haben, werden die folgenden Klassendateien angezeigt:
My.class
Poly$1.class // Class file corresponding to anonymous subclass
Poly.class
Siehe diese Klasse - Poly$1.class
. Dies ist die vom Compiler erstellte Klassendatei, die der anonymen Unterklasse entspricht, die Sie mit dem folgenden Code instanziiert haben:
new My() {};
Es ist also klar, dass eine andere Klasse instanziiert wird. Es ist nur so, dass diese Klasse erst nach der Kompilierung durch den Compiler einen Namen erhält.
Im Allgemeinen werden alle anonymen Unterklassen in Ihrer Klasse folgendermaßen benannt:
Poly$1.class, Poly$2.class, Poly$3.class, ... so on
Diese Zahlen bezeichnen die Reihenfolge, in der diese anonymen Klassen in der umschließenden Klasse erscheinen.
B
von einer abstrakten einA
, während der Teil der Konstruktion vonB
Beispiel , die aus laufendenA
‚s Konstruktor, der Laufzeittyp des Objekts ist tatsächlichA
. Nur vorübergehend.