为什么我可以匿名地子类化枚举而不是最终的类?
这段代码:
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);
}
}
打印:
我是值
I'm the 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
创建我看起来是一个匿名的 E
子类,覆盖 toString
方法,而使用最终类而不是隐式最终枚举会引发编译时错误?
Why can E.VALUE
create what appears to me to be an anonymous E
subclass, overriding the toString
method, while using a final class instead of an implicitly final enum throws a compile-time error?
更多具体来说,为什么可以 VALUE
覆盖 E
中的任何内容?我的印象是代码
More specifically, why can VALUE
override anything in E
? I was under the impression that the code
public enum E {
VALUE;
}
大致相当于
public static final class E {
public static final E VALUE = new E();
}
在这种情况下,不允许匿名性质。
in which case the anonymous nature would not be allowed.
有什么区别?为什么枚举是特别的?
What's the difference? Why are enums special?
根据:
According to the JLS:
枚举类型是隐式最终的,除非它包含至少一个具有类体的枚举
常量。
An enum type is implicitly final unless it contains at least one enum constant that has a class body.
您的示例 VALUE
有一个类体,因此 E
不是隐式最终的。
In your example, VALUE
has a class body and therefore E
is not implicitly final.
编辑以下是一个验证声明的快速示例:
Here's a quick example that validates the claim:
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()));
}
}
您可以从输出中看到编译器正在添加最终
修饰符到 E2
但不是 E
:
You can see from the output that the compiler is adding the final
modifier to E2
but not to 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
子类化,明确地尝试扩展它,例如与类Foo扩展E
或枚举栏扩展E
是根据 8.1.4。超类和子类:
Edit #2:
Even though E
is not final
and is subclassed by VALUE
, explicitly trying to extend it such as with class Foo extends E
or enum Bar extends E
is a compile-time error according to 8.1.4. Superclasses and Subclasses:
如果ClassType命名了类Enum或
任何一个编译时错误调用它。
It is a compile-time error if the ClassType names the class Enum or any invocation of it.