【问题标题】:Are enum values actually subclasses of the enum itself?枚举值实际上是枚举本身的子类吗?
【发布时间】:2014-07-25 14:48:59
【问题描述】:

所以我遇到了一些非常有用的有趣的东西。在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 构造函数的关系。

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

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

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

那么,有谁知道真正是怎么回事?

【问题讨论】:

    标签: java class enums


    【解决方案1】:

    From the JLS

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

    [...]

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

    JLS also states

    对于在E的声明体中声明的每个枚举常量cE 有一个 public static final field 类型的隐式声明 Ec 同名。该字段有一个变量初始化器 由c 组成,并使用与c 相同的注解进行注解。

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

    请注意,enum 类型也隐含为 final(您无法对它们进行子类化)。 Java 语言只允许枚举常量的这种子类化行为。

    【讨论】:

    • 所以这意味着enum 值已经是一个类,对吧?否则就不可能从中创建一个匿名类。那么这些值扩展了enum 基类,我说得对吗?
    • @jeff 抱歉,我不得不离开我的电脑。让我找到JLS的报价。每个常量都隐含地是枚举类的一个静态字段。
    【解决方案2】:

    这是枚举的一个非常强大的特性,因为每个enum 不仅是一个完全成熟的类,可以有构造函数、设置器、获取器等,而且enum 的每个单独成员都可以有自己的匿名实现主要的枚举类。

    【讨论】:

      【解决方案3】:

      您实际上是在定义匿名内部类。在你的枚举的类文件上执行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
      

      所以这不是最好的例子,因为枚举值都没有实现方法,但您可能会知道枚举实际上是什么。

      【讨论】:

        【解决方案4】:

        如果您曾经在泛型中使用过enums,您将会遇到E extends Enum&lt;E&gt;,这是定义enum 类型的正确方法。这有点奇怪,但是一旦您了解它,您就会看到它说枚举实际上扩展了自身的Enum(注意不同的情况)。所以基本上是的,组中的所有enums 似乎都扩展了基本声明类,但基本声明类实际上是Enum - 有点。

        顺便说一句 - 你也可以让enums 实现一个接口:

        interface Something {
            int getValue();
        }
        
        enum It implements Something {
            One,
            Two,
            Three;
        
            @Override
            public int getValue() {
                return ordinal();
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-11-11
          • 2019-03-25
          • 2022-08-03
          • 1970-01-01
          相关资源
          最近更新 更多