今天在code的时候看到如下定义的Enum类型,觉得很奇怪:
public enum Sex {
NONE {
@Override
public String getName() {
// TODO Auto-generated method stub
return "空";
}
},
MAN {
@Override
public String getName() {
// TODO Auto-generated method stub
return "男";
}
},
WOMEN {
@Override
public String getName() {
// TODO Auto-generated method stub
return "女";
}
};
public abstract String getName();
}
印象中Enum类型应该是被翻译成final的类,而每个成员应该都是此类的实例,为什么还能加入abstract方法,而且还能被重写呢.
随后又写了一个类:
State:
public enum State {
BUSY,
LEISURE;
}
然后使用javap -p命令反编译了一下两个枚举对象生成的.class文件:
首先是Sex.class,反编译结果如下:
//Compiled from "Sex.java"
public abstract class test.he.enumeration.Sex extends java.lang.Enum<test.he.enumeration.Sex> {
public static final test.he.enumeration.Sex NONE;
public static final test.he.enumeration.Sex MAN;
public static final test.he.enumeration.Sex WOMEN;
private static final test.he.enumeration.Sex[] $VALUES;
public static test.he.enumeration.Sex[] values();
public static test.he.enumeration.Sex valueOf(java.lang.String);
private test.he.enumeration.Sex();
public abstract java.lang.String getName();
test.he.enumeration.Sex(java.lang.String, int, test.he.enumeration.Sex$1);
static {};
}
1. 发现这里的Sex类被声明成abstract的了.
2.而且还发现系统还生成了另外3个.class文件:Sex$1.class、Sex$2.class和Sex$3.class
编译其中一个Sex$1.class:
//Compiled from "Sex.java"
final class test.he.enumeration.Sex$1 extends test.he.enumeration.Sex {
test.he.enumeration.Sex$1(java.lang.String, int);
public java.lang.String getName();
}
3.注意到这里的Sex$1已经变成包访问权限,而且被声明了final,并且继承了Sex
再使用jd-gui反编译Sex$1.class:
enum Sex$1
{
Sex$1()
{
super(str, i, null);
}
public String getName() {
return "空";
}
}
4.这个其实就是我们重写后的新的enum类,构造方法也是包访问权限
随后反编译了State.class文件:
//Compiled from "State.java"
public final class test.he.enumeration.State extends java.lang.Enum<test.he.enum
eration.State> {
public static final test.he.enumeration.State BUSY;
public static final test.he.enumeration.State LEISURE;
private static final test.he.enumeration.State[] $VALUES;
public static test.he.enumeration.State[] values();
public static test.he.enumeration.State valueOf(java.lang.String);
private test.he.enumeration.State();
static {};
}
5.发现这里的对象直接被声明成了final.
试着把abstract方法删除,直接在对象后面定义方法,发现反编译的结果大致一致
只是Sex没被声明任何关键字:public class Sex
可以理解为Sex中,可以有自己的对象,也可以有自己子类的对象,所以未声明任何关键字
在一般情况下,需要把共有方法声明为abstract方法,
因为从public static final test.he.enumeration.Sex NONE;可以知道,这里利用了多态性,在外部访问NONE时,只能访问Sex中存在的方法
其实测试一下可以发现,不需要将方法声明为abstract方法也可以访问,但是使用abstract有更好的强制性,让子类必须重写这个方法
从上面的众多结果可以发现,Enum中的每个属性都是 该类(A)的实例/该类的子类(B extends A)的实例
向Enum类(A)中的属性中添加方法或属性,该类(A)就不会被(abstract或者正常)声明为final,并且产生继承自该类的子类(B extends A),而该属性就会成为子类(B)的对象.
好吧有点绕口......不会说......
如果这个浅析有错误,希望大家指正