【问题标题】:Enum Inner Class is not recognized as Enum枚举内部类不被识别为枚举
【发布时间】:2013-09-19 06:45:41
【问题描述】:

考虑以下枚举类:

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 有点令人困惑,但您可以将其分配给 Enum,如下所示:

Enum<?> m = APlanet.MARS;

【问题讨论】:

  • 感谢您的快速响应。如何可靠地测试 Object 是否是 Enum 的实例?
  • 你这是什么意思?你可以添加一个例子吗?如果你需要做这样的事情,那么我猜你的设计有问题。

标签: java enums inner-classes


【解决方案1】:

来自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()。根据 Enum#getDeclaringClass() 方法的文档,这将返回 true:

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


但我认为枚举不能被子类化?

现在可以想到的疑问是,enum 不能被子类化。那么,如何创建 enum 的匿名子类呢?它如何扩展enum?这是因为,除非根据JLS Section 8.9 - Enums 声明一些特定于常量的类主体,否则枚举是最终的:

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

你仍然不能显式扩展enum

即使特定于常量的类体隐式创建了一个匿名子类,您也不能显式扩展enum。根据JLS Section 8.1.4 - Superclasses and Subclasses

如果 ClassType 将类命名为 Enum 或其任何调用,则会出现编译时错误。

【讨论】:

  • +1 又是this :)。并恭喜你获得“传奇”!
  • @Bohemian。啊!谢谢 :) 很高兴。
猜你喜欢
  • 1970-01-01
  • 2021-08-28
  • 1970-01-01
  • 2019-01-08
  • 1970-01-01
  • 2021-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多