枚举值实际上是枚举本身的子类吗?

时间:2014-07-25 14:49:00

标签: java class enums

所以我遇到了一些非常有用的东西。在enum中,您可以定义abstract方法,其中每个enum值都被强制为其提供实现。例如,以下内容:

public enum Test {

    RAWR ("Burninating the country side") {
        @Override
        public int doStuff() {
            return 0;
        }
    };

    private final String enumStuff;

    private Test(String enumStuff) {
        this.enumStuff = enumStuff;
    }

    public abstract int doStuff();

}

我添加了私有变量,因此您可以看到它与标准private构造函数的关系。

所以这让我想知道:与RAWR类相比,Test实际上是什么?通常情况下,这种语法会让我觉得我正在定义一个匿名的内部类,但这里看起来并不直观,因为RAWR不是匿名的。

我能想到的最接近的事情是enum的值实际上是enum本身的扩展,例如,

public class RAWR extends Test {
    @Override
    public int doStuff() {
        return 0;
    }
}

那么,有没有人知道真正正在进行什么?

4 个答案:

答案 0 :(得分:7)

From the JLS

  

枚举声明指定一个新的枚举类型,一种特殊的类类型。

     

[...]

     

枚举常量的可选类主体隐式定义了一个   匿名类声明(第15.9.5节),立即扩展   封闭枚举类型。

JLS also states

  

对于c声明正文中声明的每个枚举常量E,   E隐式声明public static final field类型为E   与c同名。该字段具有可变初始值设定项   由c组成,并使用与c相同的注释进行注释。

您声明的enum类型为Test。你声明的每个枚举常量都是Test的子类的实例,如果它有一个主体。

请注意,enum类型也隐式final(您无法将它们子类化)。 Java语言仅允许枚举常量的子类化行为。

答案 1 :(得分:1)

这是枚举的一个非常强大的功能,因为每个enum不仅是一个完全成熟的类,可以有构造函数,设置器,getter等,但enum的每个成员都可以拥有它拥有主枚举类的匿名实现。

答案 2 :(得分:1)

您实际上是在定义匿名内部类。在枚举的类文件上执行javap -c <classFile>,以查看编译时枚举的外观。

您将看到枚举只不过是一个普通类,其公共静态最终变量与枚举类型相同。您还将看到为每个变量分配了一个匿名内部类。

示例:

$ javap-c StatusCode.class

public final class de.haufe.StatusCode extends java.lang.Enum<de.haufe.StatusC                                                                                        ode> {
    public static final de.haufe.StatusCode CREATED;

    public static final de.haufe.StatusCode BAD_REQUEST;

    public static final de.haufe.StatusCode UNAUTHORIZED;

    public static final de.haufe.StatusCode NOT_FOUND;

    public static final de.haufe.StatusCode PRECONDITION_FAILED;

    public static final de.haufe.StatusCode UNSUPPORTED_MEDIA_TYPE;

    public static final de.haufe.StatusCode UNPROCESSABLE_ENTITY;

    public static final de.haufe.StatusCode LOCKED;

    public static final de.haufe.StatusCode INTERNAL_SERVER_ERROR;

    public static de.haufe.StatusCode[] values();
}

// more stuff

所以这不是最好的例子,因为没有任何枚举值实现一个方法,但你可能知道枚举实际是什么。

答案 3 :(得分:1)

如果您曾使用过enum个泛型,则会遇到E extends Enum<E>这是正确定义enum类型的方法。这有点奇怪但是一旦你了解它,你就可以看到它说的是枚举实际上扩展了Enum(注意不同的情况)。基本上是的,组中的所有enum似乎扩展了基类声明类,但基本声明类实际上是Enum - 排序。

BTW - 你也可以让enum实现一个接口:

interface Something {
    int getValue();
}

enum It implements Something {
    One,
    Two,
    Three;

    @Override
    public int getValue() {
        return ordinal();
    }
}