为什么不从Enum<E extends Enum<E>>进行扩展?

4
我遇到了以下问题,我无法从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 是 final 的。问题是为什么我不能从上面的 Enum 类继承..如果我能够继承,我应该能够调用受保护的构造函数,该构造函数具有 nameordinal 参数。 - khmarbaise
5个回答

5
你不能像那样扩展枚举。它是内置到编译器或运行时中的(不确定哪个)。
但看起来你正在尝试解决错误的问题;枚举值的序数不应具有任何功能意义。一旦你赋予它一个功能意义,它就应该有一个与“Ordinal”不同的名称。你的第二个代码片段比第一个要好得多。
通常,依赖序数进行任何操作都是不好的实践;它可能本来就不应该被公开。你唯一可以依赖的是名称和自己分配的任何值。
如果对你来说将字段命名为“ordinal”非常重要,只需使用类型安全的枚举模式(项21),这只是Enum的一种实现。

我知道依赖于ordinal()是不好的编程实践,但我有一些遗留代码需要处理。因此,我必须使用枚举模式。 - khmarbaise

4
枚举类型在编译器中得到特殊处理,而像EnumSet这样的类则基于此进行假设。枚举方法(如ordinal()name())的行为是严格定义的,自己实现以复制此行为是没有意义的。此外,在enum中声明枚举值的语法仅在enum中有效,在class中不会编译通过。
重要的是要记住,您永远不应该自己使用ordinal(),因此将其定义为适合您的问题是没有意义的。

我不想实现ordinal()和name() new。我只想能够从抽象Enum类继承,但这似乎是不可能的。ordinal()的问题在于我必须与遗留代码兼容。我想摆脱ordinal(),但目前没有机会。 - khmarbaise
@khmarbaise 在Java中获得一个具体的ordinal()值的唯一方法是对枚举值进行排序,然后可能添加填充值-第一个值为0,然后是1...(这就是为什么没有人应该直接使用ordinal()的原因)。另外唯一的方法是在编译后使用像ASM或BCEL这样的工具修改生成的字节码(我自己从未尝试过,而且可能很复杂)。 - josefx

1

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


0
例如,如果您明确实现它,则不必在构造函数中初始化“name”和“ordinal”属性。这可能会导致NPE错误。

0

枚举在语言核心和特殊用途中具有特殊含义。因此,您可以在“switch”语句中使用它们,而普通类则无法实现。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接