当前位置: 首页 > 面试题库 >

为什么我可以匿名将枚举子类化而不能最终类化?

戴鸿羽
2023-03-14
问题内容

这段代码:

public class Sandbox {
    public enum E {
        VALUE {
            @Override
            public String toString() {
                return "I'm the value";
            }
        };

        @Override
        public String toString() {
            return "I'm the enum";
        }
    }
    public static void main(String[] args) {
        System.out.println(E.VALUE);
    }
}

印刷品:

我就是价值

但是,此代码

public class Sandbox {
    public static final class C {
        @Override
        public String toString() {
            return "I'm a C";
        }
    }

    public static void main(String[] args) {
        System.out.println(new C() {
            @Override
            public String toString() {
                return "I'm anonymous";
            }
        });
    }
}

导致编译错误:

cannot inherit from final HelloWorld.C

为什么E.VALUE在我使用final类而不是隐式final枚举的同时E,创建对我来说似乎是匿名子类的类,覆盖该toString方法,却抛出了编译时错误?

更具体地说,为什么可以VALUE覆盖中的任何内容E?我对代码有印象

public enum E {
    VALUE;
}

大致相当于

public static final class E {
    public static final E VALUE = new E();
}

在这种情况下,匿名性质是不允许的。

有什么不同?为什么枚举很特别?


问题答案:

根据JLS:

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

在您的示例中,VALUE具有类主体,因此E不是隐式最终的。

编辑: 这是一个验证索赔的快速示例:

import java.lang.reflect.Modifier;

public class Sandbox {
  public enum E {
    VALUE {};
  }

  public enum E2 {
    VALUE;
  }

  public static void main(String[] args) {
    System.out.println(E.class);
    System.out.println(E.VALUE.getClass());
    System.out.println("E.VALUE is subclass of E = " + E.VALUE.getClass().getSuperclass().equals(E.class));
    System.out.println("E modifiers: " + Modifier.toString(E.class.getModifiers()));
    System.out.println("E2 modifiers: " + Modifier.toString(E2.class.getModifiers()));
  }
}

从输出中可以看到,编译器正在将final修饰符添加到,E2但没有E

class Sandbox$E
class Sandbox$E$1
E.VALUE is subclass of E = true
E modifiers: public static
E2 modifiers: public static final

编辑#2: 即使E final和由子类VALUE,明确地试图把它扩大,如用class Foo extends E或者enum Bar extends E是根据编译时错误8.1.4。超类和子类:

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



 类似资料:
  • 问题内容: Java不允许枚举位于接口内部,但是默认情况下,接口内部的每个数据成员都是。有人可以澄清吗? 问题答案: 枚举不能是最终的,因为编译器将为程序员明确为其定义实现的每个枚举条目生成子类。 此外,根据JLS第8.9节,没有实例具有自己的类主体的枚举是隐式最终的。

  • 问题内容: 我想知道为什么在Java语言中a 不能扩展。 我不是在谈论一个延伸的(这不能做,因为Java没有多重继承,而Š隐含延长),但一类的以只添加额外的方法,而不是额外的枚举值。 就像是: 要这样使用: 因此,有人可以对此限制提供理由(或将我指向正确的JLS部分)吗? 问题答案: 我认为 他们这样做 的答案来自以下问题: 在您的示例中,如何实例化MyClass?用户永远不会(通过)显式实例化枚

  • 问题内容: 在这里只能是最终的。为什么?如何在不保留为私有成员的情况下重新分配方法? 单击该如何返回?我的意思是, 问题答案: 如注释中所述,其中一些在Java 8中变得无关紧要,在Java 8中final可以隐式使用。但是,只能在匿名内部类或lambda表达式中使用有效的最终变量。 这基本上是由于Java管理闭包的方式。 创建匿名内部类的实例时,该类中使用的任何变量都将通过自动生成的构造函数复制

  • 问题内容: 我正在使用JavaScript将对象序列化为JSON字符串, 我注意到只有可枚举的对象属性才被序列化: [ 笔 ] 我想知道为什么会这样?我已经通过搜索MDN页面中,json2解析器文档。我找不到任何地方记录此行为。 我怀疑这是使用仅通过[[enumerable]]属性的循环(至少在情况下)的结果。可以使用类似的方法同时返回可枚举和不可枚举的属性。不过,这可能会导致序列化(由于反序列化

  • 我听到一些人建议在C++中使用枚举类,因为它们的类型安全。 但这到底意味着什么呢?