2

次の Enum クラスを検討してください。

public enum APlanet {
    VENUS   ()  {public void stuff(){}},
    EARTH   () {public void stuff(){}},
    MARS    ()  {public void stuff(){}};
    public abstract void stuff();
}

public enum BPlanet {
    VENUS   (),
    EARTH   (),
    MARS    ();
}

その後APlanet.MARS.getClass().isEnum()、false をBPlanet.MARS.getClass().isEnum()返しますが、true を返します。なんで?APlanet.getDeclaringClass().isEnum()が正しく true を返すことに注意してください。

具体的には、オブジェクトが Enum であるかどうかを確実にテストしようとしています。

Object a = APlanet.MARS;
Object b = BPlanet.MARS;
a.getClass().isEnum() /* returns false */
b.getClass().isEnum() /* returns true  */

まだ

Enum.class.isAssignableFrom(a.getClass()); /* returns true */

内部クラス APlanet.MARS が Enum ではないのに、次のように Enum に割り当てることができるのは少し混乱します。

Enum<?> m = APlanet.MARS;
4

1 に答える 1

8

JLS セクション 8.9.1から- 列挙型定数:

列挙型定数のオプションのクラス本体は、直接囲んでいる列挙型を拡張する匿名クラス宣言 (§15.9.5) を暗黙的に定義します。クラス本体は、無名クラスの通常の規則によって管理されます。特に、コンストラクターを含めることはできません。

最初の列挙型で定数固有のクラス本体を宣言しました。

 MARS ()  {public void stuff(){}}; // The curly braces defines a class body

これにより、匿名クラスが作成されます。したがって、MARS.getClass()はこの匿名クラスの Class インスタンスを返しますが、これはEnum.


これは、インターフェイスの匿名サブクラスのインスタンス、または次のような他のクラスを作成する場合に似ています。

SomeInterface obj = new SomeInterface() { /** Method definitions **/ };

そして、obj.getClass()戻ってこないでしょうSomeInterfaceが、ClassContainingThatDeclaration$1.

APlanet.getDeclaringClass().isEnum()が正しく true を返すことに注意してください

私はそれが - であるべきだと思いAPlanet.MARS.getDeclaringClass().isEnum()ます。Enum#getDeclaringClass()メソッドのドキュメントに従って、それは true を返します。

この列挙型定数の列挙型に対応する Class オブジェクトを返します。2 つの列挙型定数 e1 と e2 は、 の場合にのみ、同じ列挙型になりe1.getDeclaringClass() == e2.getDeclaringClass()ます。Object.getClass()(このメソッドによって返される値は、定数固有のクラス本体を持つ列挙型定数のメソッドによって返される値とは異なる場合があります。)


しかし、列挙型はサブクラス化できないと思いましたか?

ここで頭に浮かぶ疑問は、enumサブクラス化できないということです。では、enum の匿名サブクラスを作成するにはどうすればよいでしょうか。どのように拡張できenumますか?これは、 JLS セクション 8.9 - Enums に従って、定数固有のクラス本体を宣言しない限り、列挙型が final であるためです。

列挙型は、クラス本体を持つ列挙型定数が少なくとも 1 つ含まれていない限り、暗黙的に final です。

を明示的に拡張することはまだできませんenum:

定数固有のクラス本体は暗黙的に匿名サブクラスを作成しますが、. を明示的に拡張することはできませんenum。JLSセクション 8.1.4 - スーパークラスとサブクラス:

ClassType がクラス Enum またはその呼び出しに名前を付ける場合、コンパイル時エラーになります。

于 2013-09-14T19:42:35.820 に答える