考虑以下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;
答案 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}}方法的文档:
返回与此枚举常量的枚举类型对应的Class对象。当且仅当
e1.getDeclaringClass() == e2.getDeclaringClass()
时,两个枚举常量e1和e2具有相同的枚举类型。 (此方法返回的值可能与Object.getClass()
方法返回的具有常量特定类主体的枚举常量的值不同。)
现在可能出现的疑问是,enum
不能被分类。那么,如何创建枚举的匿名子类?它如何扩展enum
?这是因为,枚举是最终的,除非它按照Enum#getDeclaringClass()
声明一些特定于常量的类体:
枚举类型是隐式final的,除非它包含至少一个具有类主体的枚举常量。
enum
:即使特定于常量的类体隐式创建了一个匿名子类,也无法显式扩展enum
。根据{{3}}:
如果ClassType将类命名为Enum或对其进行任何调用,那么这是一个编译时错误。