mat*_*ath 5 java enums extends code-generation final
当我指定这样的枚举时:
enum Color { RED }
Run Code Online (Sandbox Code Playgroud)
生成的代码javap -p Color如下所示:
final class Color extends java.lang.Enum<Color> {
public static final Color RED;
private static final Color[] $VALUES;
public static Color[] values();
public static Color valueOf(java.lang.String);
private Color();
private static Color[] $values();
static {};
}
Run Code Online (Sandbox Code Playgroud)
但是,当我添加自定义扩展(例如显式构造函数)时,例如:
enum Color {
RED,
Color() {}
}
Run Code Online (Sandbox Code Playgroud)
我明白了:
class Color extends java.lang.Enum<Color> {
public static final Color RED;
public static final Color Color;
private static final Color[] $VALUES;
public static Color[] values();
public static Color valueOf(java.lang.String);
private Color();
private static Color[] $values();
static {};
}
Run Code Online (Sandbox Code Playgroud)
缺少final生成的类 Color 的修饰符。但是,我无法扩展Color(像往常一样):
final class B extends Color {}
Run Code Online (Sandbox Code Playgroud)
编译器给出:
error: enum types are not extensible
final class B extends Color {}
^
1 error
Run Code Online (Sandbox Code Playgroud)
那么为什么final在向枚举类添加自定义代码时缺少修饰符呢?我想无论如何,防止子类化 Color 是通过编译器的健全性检查来执行的(又名:如果超类 typeof enum => 拒绝),对吗?
我在用OpenJDK 17.0.2
您没有在此处添加显式构造函数:
\nenum Color {\n RED,\n\n Color() {}\n}\nRun Code Online (Sandbox Code Playgroud)\n相反,您添加了另一个名为 的枚举常量Color,其类主体为空。这在意想不到的线条中很明显javap:
public static final Color Color;\nRun Code Online (Sandbox Code Playgroud)\n因此,必须创建一个(空)匿名类,它继承自枚举类,作为枚举常量“ Color”的类。因此,枚举Color不能是最终的。你应该看到一个额外的Color$1.class您应该在 javac 输出文件夹中
Java 语言规范中规定枚举是否应为最终枚举,如下所示:
\n\n\n枚举类要么是隐式最终的,要么是隐式密封的,如下所示:
\n\n
\n- 如果枚举类的声明不包含具有类主体 (\xc2\xa78.9.1) 的枚举常量,则该枚举类是隐式最终的。
\n- [...]
\n
枚举Color具有具有主体的枚举常量Color,因此它不是final。
将构造函数添加到枚举的正确方法是使用 . 将其与常量分开;。,用于分隔常数。例子:
enum Color {\n RED, GREEN, BLUE;\n\n Color() {}\n}\nRun Code Online (Sandbox Code Playgroud)\n正如预期的那样,这个Color枚举是final.