ここで、クラスのインスタンスを作成しています
いいえ、ここでは抽象クラスのインスタンスを作成していません。むしろ、抽象クラスの匿名サブクラスのインスタンスを作成しています。そして、サブクラス objectを指す抽象クラス参照でメソッドを呼び出しています。
この動作は、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
これらの番号は、それらの匿名クラスが含まれているクラスに表示される順序を示します。