1. ホーム
  2. java

[解決済み] 抽象的なクラスをインスタンス化することはできますか?

2022-03-17 22:14:33

質問

面接で、「抽象クラスをインスタンス化できますか?

私の答えは、「できない」でした。しかし、面接官は私に「違うよ、できるんだ」と言いました。

私はこのことについて少し議論しました。すると、「家で自分でやってみろ」と言われました。

abstract class my {
    public void mymethod() {
        System.out.print("Abstract");
    }
}

class poly {
    public static void main(String a[]) {
        my m = new my() {};
        m.mymethod();
    }
}

ここでは、自分のクラスのインスタンスを生成して、抽象クラスのメソッドを呼び出しています。どなたか説明していただけませんか?面接の時、私は本当に間違っていたのでしょうか?

どのように解決するのですか?

<ブロッククオート

ここでは、私のクラスのインスタンスを作成しています。

いいえ、ここでは抽象クラスのインスタンスを作成しているのではありません。むしろ、あなたは 匿名サブクラス の抽象クラスです。そして、そのメソッドを自分の 抽象クラス を指す参照。 サブクラスオブジェクト .

この動作は、以下のように明確に記載されています。 JLS - セクション番号 15.9.1 : -

クラスインスタンス生成式がクラスボディで終わっている場合は インスタンス化されるクラスは無名クラスである。それなら

  • Tがクラスを示す場合、Tで指定されたクラスの匿名直下クラスが宣言されます。を宣言した場合、コンパイル時のエラーとなる。 のクラスはfinalクラスである。
  • T がインタフェースを表す場合、T で名付けられたインタフェースを実装する Object の匿名直接サブクラスが宣言されます。
  • いずれの場合も、サブクラスの本体は、クラスインスタンス生成式で指定されたClassBodyとなります。
  • インスタンス化されるクラスは、匿名サブクラスです。

強調は私です。

また JLS - セクション番号 12.5 について書かれています。 オブジェクト作成プロセス . その中の一文をここに引用します。-

<ブロッククオート

新しいクラスインスタンスが作成されるたびに、メモリ空間が割り当てられます。 そのクラスで宣言されたすべてのインスタンス変数のためのスペースがあります。 の各スーパークラスで宣言されたすべてのインスタンス変数が含まれます。 クラス型は、非表示にされる可能性のあるインスタンス変数をすべて含みます。

新しく生成されたオブジェクトへの参照が返される直前に その結果、指示されたコンストラクタが処理され、新しい オブジェクトを以下の手順で作成します。

完全な手順については、私が提供したリンク先で読むことができます。


インスタンス化されるクラスが、実質的に 匿名サブクラス の場合、両方のクラスをコンパイルする必要があります。これらのクラスを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

これらの数字は、それらの匿名クラスが囲むクラスの中に現れる順序を表しています。