为什么一个类不能扩展枚举?

我想知道为什么在Java语言中一个class不能扩展enum

我不是在谈论扩展enum (由于java没有多重inheritance,而且enum隐式地扩展了java.lang.Enum ),因此无法完成enum ,但是按顺序extends enum的类只添加额外的方法,而不是额外的枚举值。

就像是:

 enum MyEnum { ASD(5), QWE(3), ZXC(7); private int number; private asd(int number) { this.number=number; } public int myMethod() { return this.number; } } class MyClass extends MyEnum { public int anotherMethod() { return this.myMethod()+1; } } 

要像这样使用:

 System.out.println(MyClass.ASD.anotherMethod()); 

那么,任何人都可以为此限制提供理由(或指向正确的JLS部分)吗?

我认为他们为什么这样做的答案来自这个问题:

在您的示例中,您将如何实例化MyClass? 枚举永远不会被用户显式实例化(通过new MyEnum() )。 你必须做像MyClass.ASD这样的事情但不确定它是如何工作的。

基本上,我不知道什么语法可以用于您的建议添加。 这可能就是为什么他们让他们最终等等……

编辑增加

如果原始Enum的作者提前计划(不太可能),并且你不太担心线程安全,你可以做这样的事情:(顺便说一句,我可能会尖叫任何在生产代码中实际执行此操作的人,YMMV )

 public enum ExtendibleEnum { FOO, BAR, ZXC; private Runnable anotherMethodRunme; // exact Interface will vary, I picked an easy one // this is what gets "injected" by your other class public void setAnotherMethodRunMe(Runnable r) { // inject here anotherMethodRunme= r; } public void anotherMethod() { // and this behavior gets changed anotherMethodRunme.run(); } } 

你无法扩展enum 。 它们是隐含的final 。 来自JLS§8.9 :

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

此外,来自JLS§8.1.4 – 超类和子类 :

如果ClassType命名类Enum或对其进行任何调用,则为编译时错误。

基本上, enum是一组枚举的预定义常量。 因此,该语言允许您在switch-cases使用枚举。 例如,通过允许扩展它们,不会使它们成为开关案例的合格类型。 除此之外,扩展枚举的类或其他枚举的实例也将是您扩展的枚举的实例。 这基本上打破了enum的目的。

在Java 1.5之前的古代,你可能会做这样的枚举:

 public class MyEnum { public static final MyEnum ASD = new MyEnum(5); public static final MyEnum QWE = new MyEnum(3); public static final MyEnum ZXC = new MyEnum(7); private int number; private MyEnum(int number) { this.number = number; } public int myMethod() { return this.number; } } 

这个数字有两个重要的事情:

  • 私有构造函数,不允许从外部实例化该类
  • 实际的“枚举”值存储在静态字段中

即使它不是最终的,当你扩展它时,你会发现编译器需要一个显式的构造函数,反过来需要调用超级构造函数,这是不可能的,因为那个是私有的。 另一个问题是超类中的静态字段仍然存储该超类的对象而不是扩展的对象。 我认为这可能是一个解释。

枚举的重点是创建一组封闭的可能值。 这样可以更容易地推断出枚举类型的值是什么 – 对于程序员来说更容易,对编译器来说也更容易(例如,这种封闭性可以让它在交换机中有效地处理枚举)。 允许类扩展枚举将打开一组可能的值; enum会给你带来什么样的普通class不会?