【问题标题】:Why not extending from Enum<E extends Enum<E>>为什么不从 Enum<E 扩展扩展 Enum<E>>
【发布时间】:2013-06-20 15:13:41
【问题描述】:

我偶然发现了以下问题,我无法从 Java 1.5(java.lang 包)中定义的此类扩展和实现

public abstract class Enum<E extends Enum<E>> {...
}..

我遇到的问题是创建我自己的具有不同序数值的枚举类型。我不想通过使用不同的序数名称来实现它,比如 getCode() 等。所以我想我可以去扩展上面的类。

public final class XYZ extends Enum<XYZ> { //Does not work.
  //
  A("A", 1),
  B("B", 7);
  .
}

我知道我可以做到以下几点:

public enum NEWEnum {
   A(1),
   B(7);

   private int code;
   private NEWEnum(int code) {
     this.code = code;
   }
   public int getCode() {
     return this.code;
   }
}

我更喜欢在 Enum 中使用通常的命名,例如 ordinal() 和 name()。

【问题讨论】:

  • @RayToal 我知道ordinalname 是最终的。问题是为什么我不能从上面的 Enum 类扩展..如果我可以扩展,我应该能够调用具有 nameordinal 参数的受保护构造函数。

标签: java enums


【解决方案1】:

你不能像那样扩展 Enum。它内置于编译器或运行时(不确定是哪个)。

但您似乎在尝试解决错误的问题;枚举值的序数不应该具有任何功能意义。一旦你给它一个,它应该有一个不同于“Ordinal”的名字。您的第二个代码 sn-p 远远优于您的第一个代码。

一般来说,任何事情都依赖序数是不好的做法;它可能一开始就不应该被曝光。您唯一可以依赖的是名称,以及您为自己分配的任何值。

如果将字段命名为“序数”对您来说很重要,只需使用 typesafe enum pattern (item 21),Enum 只是它的一个实现。

【讨论】:

  • 我知道依赖 ordinal() 是不好的做法,但我有遗留代码,我必须处理它。所以我必须采用枚举模式。
【解决方案2】:

Enum 得到编译器的特殊处理,并且 EnumSet 等类基于这种处理做出假设。像ordinal()name() 这样的枚举方法的行为是严格定义的,并且自己实现它们来复制这种行为是没有意义的。此外,声明枚举值的语法仅在 enum 中有效,不会在 class 中编译。

重要的是要记住,你永远不应该自己使用ordinal(),所以定义它来适应你的问题是没有意义的。

【讨论】:

  • 我不想实现 ordinal() 和 name() new。我只是不想能够从似乎不可能的抽象 Enum 类扩展。 ordinal() 的问题是我有必须兼容的遗留代码。我不想摆脱 ordinal() 但目前我没有机会。
  • @khmarbaise 在 java 中获得具体的 ordinal() 值的唯一方法是对枚举值进行排序并可能添加填充值 - 第一个值 0 然后 1,...(这就是为什么没有人应该直接使用 ordinal() )。唯一的另一种方法是在使用 ASM 或 BCEL 之类的东西编译后修改生成的字节码(我自己从来没有做过,可能很复杂)。
【解决方案3】:

Enum 类在 Java 中是特殊的,因为它用于实现 Enum 语言功能。因此,它不仅像 Java 中的任何其他类一样,而且更加特殊(例如 String+ 运算符对其进行了重载,或者像装箱的类)。要使这些功能正常工作,枚举需要特殊要求(我猜是连续序数)。因此,Java 语言规范 explicitly forbids 手动继承自 Enum 类。

【讨论】:

    【解决方案4】:

    枚举在语言核心和特殊用途中具有特殊意义。因此,您可以在switch 语句中使用它们,这对于普通类是不可能的。

    【讨论】:

      【解决方案5】:

      例如,如果显式实现它,则不必在构造函数中初始化“name”和“ordinal”的属性。以后可能会导致NPE。

      【讨论】:

        猜你喜欢
        • 2011-01-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-01
        • 1970-01-01
        • 2016-10-28
        • 2010-11-24
        相关资源
        最近更新 更多