ここでは、クラスのインスタンスを作成しています
いいえ、ここでは抽象クラスのインスタンスを作成していません。むしろ、抽象クラスの無名サブクラスのインスタンスを作成しています。そして、サブクラスオブジェクトを指す抽象クラス参照でメソッドを呼び出しています。
この動作はJLSに明確にリストされています-セクション#15.9.1:-
クラスインスタンス作成式がクラス本体で終了する場合、インスタンス化されるクラスは匿名クラスです。次に:
- Tがクラスを表す場合、Tによって指定されたクラスの匿名の直接サブクラスが宣言されます。Tで示されるクラスが最終クラスである場合は、コンパイル時エラーです。
- Tがインターフェースを表す場合、Tによって指定されたインターフェースを実装するObjectの匿名の直接サブクラスが宣言されます。
- どちらの場合でも、サブクラスの本体は、クラスインスタンス作成式で指定されたClassBodyです。
- インスタンス化されるクラスは、無名のサブクラスです。
強調鉱山。
また、JLS-セクション#12.5では、オブジェクト作成プロセスについて読むことができます。。その中の1つのステートメントをここで引用します。-
新しいクラスインスタンスが作成されるたびに、クラス型で宣言されたすべてのインスタンス変数と、クラス型の各スーパークラスで宣言されたすべてのインスタンス変数(非表示になっている可能性があるすべてのインスタンス変数を含む)のためのスペースがメモリ空間に割り当てられます。
新しく作成されたオブジェクトへの参照が結果として返される直前に、次の手順を使用して、示されたコンストラクターが処理され、新しいオブジェクトが初期化されます。
私が提供したリンクで完全な手順について読むことができます。
インスタンス化されているクラスがAnonymous SubClassであることを実際に確認するには、両方のクラスをコンパイルするだけです。これらのクラスを2つの異なるファイルに配置するとします。
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();
}
}
次に、両方のソースファイルをコンパイルします。
javac My.java Poly.java
ソースコードをコンパイルしたディレクトリに、次のクラスファイルが表示されます。
My.class
Poly$1.class // Class file corresponding to anonymous subclass
Poly.class
そのクラスを参照してください- Poly$1.class
。これは、以下のコードを使用してインスタンス化した無名サブクラスに対応するコンパイラーによって作成されたクラスファイルです。
new My() {};
したがって、インスタンス化されている別のクラスがあることは明らかです。それだけです。そのクラスには、コンパイラーによるコンパイル後にのみ名前が付けられます。
一般に、クラス内のすべての匿名サブクラスには、次のように名前が付けられます。
Poly$1.class, Poly$2.class, Poly$3.class, ... so on
これらの番号は、それらの匿名クラスが外側のクラスに現れる順序を示します。
B
から非抽象クラスを派生させる場合、オブジェクトの実行時の型は実際にはです。ただし、一時的なものです。A
B
A
A