java中枚举实现原理
介绍
枚举是java5新增的特性,我们可以用来替代以前用常量完成的功能。java对枚举的支持还有EnumSet,EnumMap等工具类。
使用
public enum UserGenderEnum {
MALE("0", "男"),
FEMALE("1", "女"),
NOT_KNOWN("2", "未知");
private final String code;
private final String info;
UserGenderEnum(String code, String info) {
this.code = code;
this.info = info;
}
public String getCode() {
return code;
}
public String getInfo() {
return info;
}
}
public class Client {
public static void main(String[] args) {
UserGenderEnum[] userGenderEnums = UserGenderEnum.values();
for (UserGenderEnum genderEnum : userGenderEnums) {
System.out.println("enum:" + genderEnum + "," + genderEnum.name() + "," + genderEnum.ordinal());
}
System.out.println(UserGenderEnum.valueOf("MALE"));
}
}
输出结果为
enum:MALE,MALE,0
enum:FEMALE,FEMALE,1
enum:NOT_KNOWN,NOT_KNOWN,2
MALE
我们看一下枚举反编译后的结果,如何反编译看上一篇文章
public final class UserGenderEnum extends Enum<UserGenderEnum> {
public static final /* enum */ UserGenderEnum MALE = new UserGenderEnum("MALE", 0, "0", "\u7537");
public static final /* enum */ UserGenderEnum FEMALE = new UserGenderEnum("FEMALE", 1, "1", "\u5973");
public static final /* enum */ UserGenderEnum NOT_KNOWN = new UserGenderEnum("NOT_KNOWN", 2, "2", "\u672a\u77e5");
private final String code;
private final String info;
private static final /* synthetic */ UserGenderEnum[] $VALUES;
public static UserGenderEnum[] values() {
return (UserGenderEnum[])$VALUES.clone();
}
public static UserGenderEnum valueOf(String name) {
return Enum.valueOf(UserGenderEnum.class, name);
}
private UserGenderEnum(String string, int n, String code, String info) {
super(string, n);
this.code = code;
this.info = info;
}
public String getCode() {
return this.code;
}
public String getInfo() {
return this.info;
}
static {
$VALUES = new UserGenderEnum[]{MALE, FEMALE, NOT_KNOWN};
}
}
枚举类默认继承Enum抽象类,这也是枚举不能继承其他类的原因。编译器帮我们创建了3个静态实例,并将构造器设为私有,在我们的构造参数基础上增加了name和ordinal两个参数,indinal可以看做实例的索引。接下来我们看一下valueOf方法的实现原理,
这个方法是编译器帮我们创建的,反编译后才可以看到,
实际上调用的是Enum内部的方法,
继续跟到Class类
终于看到了最终实现,可以看到Class还是调用了UserGenderEnum的values方法,上面可以看到values方法返回的是实例的数组,兜兜转转有回到了UserGenderEnum。
接下来看一下switch对枚举的支持,
public class Client {
public static void main(String[] args) {
UserGenderEnum male = UserGenderEnum.MALE;
switch (male) {
case MALE:
System.out.println("male");
break;
case FEMALE:
System.out.println("female");
break;
case NOT_KNOWN:
System.out.println("not_known");
break;
}
}
}
反编译结果为
public class Client {
public static void main(String[] args) {
UserGenderEnum male = UserGenderEnum.MALE;
switch (male.ordinal()) {
case 1: {
System.out.println("male");
break;
}
case 2: {
System.out.println("female");
break;
}
case 3: {
System.out.println("not_known");
}
}
}
}
可以看到最终还是转成了int类型。