本文参考
今天在Java Language Specification上偶然看到一条关于枚举的语法特点说明
An enum declaration is implicitly final unless it contains at least one enum constant that has a class body
不是很理解此处Class Body的所指,查阅了一些关于Java enum的语法介绍和stack overflow上的回答,对这句话有了一定的理解
https://stackoverflow.com/questions/9891613/why-cant-a-java-enum-be-final
不含Class Body的enum声明
public enum Color1 {
RED("红色"),
GREEN("绿色"),
BLUE("蓝色");
private String description;
Color(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
}
不含Class Body的反编译结果
public final class Color1 extends Enum<Color1> {
public static final /* enum */ Color1 RED = new Color1("RED", 0, "u7ea2u8272");
public static final /* enum */ Color1 GREEN = new Color1("GREEN", 1, "u7effu8272");
public static final /* enum */ Color1 BLUE = new Color1("BLUE", 2, "u84ddu8272");
private String description;
private static final /* synthetic */ Color1[] $VALUES;
public static Color1[] values() {
return (Color1[])$VALUES.clone();
}
public static Color1 valueOf(String name) {
return Enum.valueOf(Color1.class, name);
}
private Color1(String string, int n, String description) {
super(string, n);
this.description = description;
}
public String getDescription() {
return this.description;
}
static {
$VALUES = new Color1[]{RED, GREEN, BLUE};
}
}
含Class Body的enum声明
这个例子中无法体现"至少有一个实例包含Class Body"的语法特点,但是后期验证确实如此,有兴趣可以改下代码自行尝试
public enum Color2 {
RED {
@Override
public String getDescription() {
return "红色";
}
},
GREEN {
@Override
public String getDescription() {
return "绿色";
}
},
BLUE {
@Override
public String getDescription() {
return "蓝色";
}
};
public abstract String getDescription();
}
含Class Body的反编译结果
public abstract class Color2 extends Enum<Color2> {
public static final /* enum */ Color2 RED = new /* Unavailable Anonymous Inner Class!! */;
public static final /* enum */ Color2 GREEN = new /* Unavailable Anonymous Inner Class!! */;
public static final /* enum */ Color2 BLUE = new /* Unavailable Anonymous Inner Class!! */;
private static final /* synthetic */ Color2[] $VALUES;
public static Color2[] values() {
return (Color2[])$VALUES.clone();
}
public static Color2 valueOf(String name) {
return Enum.valueOf(Color2.class, name);
}
private Color2(String string, int n) {
super(string, n);
}
public abstract String getDescription();
/* synthetic */ Color2(String x0, int x1, 1 x2) {
this(x0, x1);
}
static {
$VALUES = new Color2[]{RED, GREEN, BLUE};
}
}
结论
enum实际上是一种特殊的class声明,enum实例(如上面代码示例中的RED、GREEN和BLUE)都被隐式地声明为public static final
当enum实例包含Class Body时,这种写法实际上生成了一个继承enum的特殊的内部类,所以enum声明不能够是final(声明为final的类无法被继承)
另外一个注意点,编译器不一定为enum声明隐式地添加public修饰符,若enum声明被包含在某个接口或类内,Java接口在编译时会自动为enum类型加上public static修饰符,而Java类在编译时会自动为 enum 类型加上static修饰符,具体可以参考这篇文章: