【问题标题】:Why can't the super constructor be invoked from an enum constructor?为什么不能从枚举构造函数中调用超级构造函数?
【发布时间】:2011-05-30 07:58:00
【问题描述】:
public enum A {
     A(1);

     private A(int i){
     }

     private A(){
         super(); // compile - error
             // Cannot invoke super constructor from enum constructor A()
     }

}

这是enum A 的层次结构从abstract java.lang.Enum 扩展java.lang.Object

Class c = Class.forName("/*path*/.A");
System.out.println(c.getSuperclass().getName());
System.out.println(Modifier.toString(c.getSuperclass().getModifiers()).contains("abstract"));
System.out.println(c.getSuperclass().getSuperclass().getName());

【问题讨论】:

    标签: java reflection enumeration superclass


    【解决方案1】:

    事实上,您不能将enum 声明为扩展另一个类。因此,enum 只有一个可能的 super 构造函数。

    我猜,因为你不能链接到 super() 以外的任何东西,他们认为在 enum 构造函数中允许使用 super 根本不值得。

    无论如何,你都不会失去任何东西。

    【讨论】:

    • 我认为,初始化。当 super()->super()->super()->Object 到达 Object.那么,如何在不调用 super() 的情况下对其进行初始化,因此永远不会到达 Object 那么如何从 java.lang.Object 扩展它
    • 嗯???我没有说没有调用超级构造函数。我只是说只能有一个这样的超级构造函数,因此super() syntax 将是多余的。 (我想你明白当你省略 super 调用时在普通构造函数中会发生什么......)
    【解决方案2】:

    来自枚举上的Java Tutorial

    所有枚举都隐式扩展 java.lang.枚举。由于Java没有 支持多重继承,一个枚举 不能扩展其他任何东西。

    您无法调用 super() 构造函数,因为编译器会自动将隐藏调用 super(name, ordinal) 插入到您定义的任何构造函数中。

    【讨论】:

    • 感谢您的评论。 A 类不从任何其他类扩展。只想调用 super() 来查看它的继承层次树。 A->java.lang.Enum->java.lang.Object 所以我有一个正确的调用 super() 到 java.lang.Enum 然后 super() 到 java.lang.Object
    • 枚举是“特殊的”。你有“权利”在普通类上调用super,但枚举有更多限制。
    • 我的问题是,为什么?
    • 为什么不呢?为什么不需要在语言中增加额外的复杂性?也许你应该给我们一个想要这样做的有效用例。
    • 我的意思是,这与 OO 哲学背道而驰。作为一个对象而不是(调用)对象?我认为枚举没有任何特殊原因看这个。抽象类 A{}; B 类扩展 A { 私有 B() { super(); }} 所以它在这里也没用,但它是合法的。我认为它背后有不同的逻辑,或者他们(java核心开发人员)只是闲逛来编写代码
    【解决方案3】:

    枚举在编译器和运行时级别意味着很多魔法,以确保 == 比较始终有效:

    尝试显式实例化枚举类型是编译时错误(第 15.9.1 节)。 Enum 中的 final clone 方法确保永远不会克隆枚举常量,而序列化机制的特殊处理确保永远不会由于反序列化而创建重复的实例。禁止枚举类型的反射实例化。这四件事一起确保枚举类型的实例不存在超出枚举常量定义的实例。

    Java Language Specification 8.9 节

    没有无参数的 Enum() 构造函数,只有 Enum(String name, int ordinal)。但是允许用错误的参数调用那个显然会造成麻烦。

    【讨论】:

    • 感谢您的评论。让我们看看这个例子。抽象类A;和 B 类扩展 A { private B(){super()}} 。你可以这样做,但不能在枚举中。为什么 ? A 也没有任何构造函数,但在运行时添加了 super() 。为什么不使用枚举?
    • 如果没有构造函数,Java会创建一个不带参数的。如果添加构造函数 A(String bla),则无参数 super() 将不再起作用。枚举真的很特别,有很多隐藏的魔法在发生。编译器/运行时插入对 super(name, index) 的调用。使用正确的参数完成此调用至关重要,因此编译器有一个特殊情况,可以防止手动调用超级构造函数。换句话说:枚举的内部结构是一个肮脏的黑客。
    【解决方案4】:

    因为没有 super() 构造函数,请参阅 dogbane 的答案,并且因为编译器会自动插入所需的 super(...) 调用,同上。

    为什么会出现这个问题?

    【讨论】:

    • 我认为这是一个问题,因为在构造函数中使用 super 的编码标准/样式。它被称为标准,因为它不必有意义。
    • @01:如果您的编码标准告诉您调用不存在的超类构造函数,那么它就存在严重错误。您更有可能误解了要求。您必须为某些作为构造函数参数存在的 x,y,... 调用 super(x,y,...)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-16
    • 1970-01-01
    相关资源
    最近更新 更多