枚举内部类不被识别为枚举

时间:2013-09-14 19:34:54

标签: java enums inner-classes

考虑以下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。

具体来说,我正在尝试可靠地测试Object是否为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<?> m = APlanet.MARS;

1 个答案:

答案 0 :(得分:8)

来自JLS Section 8.9.1 - Enum Constants

  

枚举常量的可选类体隐式定义了一个匿名类声明(第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()。根据{{​​3}}方法的文档:

,这将返回true
  

返回与此枚举常量的枚举类型对应的Class对象。当且仅当e1.getDeclaringClass() == e2.getDeclaringClass()时,两个枚举常量e1和e2具有相同的枚举类型。 (此方法返回的值可能与Object.getClass()方法返回的具有常量特定类主体的枚举常量的值不同。)


但我认为enum不能被子类化?

现在可能出现的疑问是,enum不能被分类。那么,如何创建枚举的匿名子类?它如何扩展enum?这是因为,枚举是最终的,除非它按照Enum#getDeclaringClass()声明一些特定于常量的类体:

  

枚举类型是隐式final的,除非它包含至少一个具有类主体的枚举常量。

您仍然无法明确扩展enum

即使特定于常量的类体隐式创建了一个匿名子类,也无法显式扩展enum。根据{{​​3}}:

  

如果ClassType将类命名为Enum或对其进行任何调用,那么这是一个编译时错误。