java的枚举Enum
enum枚举类型是jdk1.5之后出来的,主要的作用是来替换我们自己定义的常量类。
Enum的使用
- 简单的定义就是下面的样子。
public enum Test {
APPLE,BANANA,PEAR
}
- 平时使用如下。可以自己定义如下,注意:
- enum类的所有东西都要写在声明的APPLE之后。
- 构造方法要私有。
public class Test {
//enum类
public enum EnumDemo{
APPLE(1),BANANA(2),PEAR(3);
private int i;
private EnumDemo(int i){
this.i=i;
}
}
//运行测试
public static void main(String[] args) {
System.out.println(EnumDemo.APPLE);
}
}
结果为:APPLE
如果想输出我们在构造方法中的值,则要重写toString()方法覆盖,如:
public String toString(){
return i+"";
}
结果就是我们定义的枚举的值。
- 枚举常用方法
方法 | 解释 |
---|---|
name() | 声明的枚举的名字:如APPLLE |
ordianl() | 返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零) |
valuesOf(String name) | 返回指定名称的枚举常量 |
valuesOf(class c,String name) | 返回指定名称的指定枚举类型的枚举常量 |
values() | 返回所有的枚举常量数组 |
compareTo(E e) | 比较枚举常量值的大小 |
public class Test {
//enum类
public enum EnumDemo{
APPLE(1),BANANA(2),PEAR(3);
private int i;
private EnumDemo(int i){
this.i=i;
}
public String toString(){
return i+"";
}
}
//运行测试
public static void main(String[] args) {
//name(),ordinal()方法
System.out.println(EnumDemo.APPLE);
System.out.println(EnumDemo.APPLE.name());
System.out.println(EnumDemo.APPLE.ordinal());
//valueOf方法
EnumDemo ed=EnumDemo.valueOf("APPLE");
System.out.println("ValueOf:name="+ed.name()+"...i="+ed+"...ordinal="+ed.ordinal());
//values
EnumDemo[] eds=EnumDemo.values();
for(EnumDemo enumDemo:eds){
System.out.println("Values:name="+enumDemo.name()+"...i="+enumDemo+"...ordinal="+enumDemo.ordinal());
}
//compareTo
System.out.println(EnumDemo.BANANA.compareTo(EnumDemo.APPLE));
System.out.println(EnumDemo.BANANA.equals(EnumDemo.APPLE));
}
}
//运行结果
1
APPLE
0
ValueOf:name=APPLE...i=1...ordinal=0
Values:name=APPLE...i=1...ordinal=0
Values:name=BANANA...i=2...ordinal=1
Values:name=PEAR...i=3...ordinal=2
1
false
Enum分析
我们通过在cmd中输入“javap -p Test$EnumDemo.class”反编译可以如下代码:
public final class com.wulei.Enum.Test$EnumDemo extends java.lang.Enum<com.wulei.Enum.Test$EnumDemo> {
public static final com.wulei.Enum.Test$EnumDemo APPLE;
public static final com.wulei.Enum.Test$EnumDemo BANANA;
public static final com.wulei.Enum.Test$EnumDemo PEAR;
private int i;
private static final com.wulei.Enum.Test$EnumDemo[] ENUM$VALUES;
static {};
private com.wulei.Enum.Test$EnumDemo(java.lang.String, int, int);
public java.lang.String toString();
public static com.wulei.Enum.Test$EnumDemo[] values();
public static com.wulei.Enum.Test$EnumDemo valueOf(java.lang.String);
}
- 可以看到EnumDemo继承java.lang.Enum
- 声明的枚举常量其实就是EnumDemo类的static final对象,EnumDemo.APPLE.name()所以可以调用父类Enum中的方法。
- 因为是final不能被继承,而extends Enum不能继承。
- 为什么构造方法要私有private?因为已经在static{}静态代码块中初始化了。
Enum源码
public abstract class Enum<E extends Enum<E>>
implements Comparable<E>, Serializable {
private final String name;
// 当前枚举常量名称
public final String name() {
return name;
}
private final int ordinal;
// 当前枚举常量次序,从0开始
public final int ordinal() {
return ordinal;
}
// 专有构造器,我们无法调用。该构造方法用于由响应枚举类型声明的编译器发出的代码。
protected Enum(String name, int ordinal) {
this.name = name;
this.ordinal = ordinal;
}
// 返回枚举常量的名称,默认是返回name值。可以重写该方法,输出更加友好的描述。
public String toString() {
return name;
}
// 比较当前枚举常量是否和指定的对象相等。因为枚举常量是单例的,所以直接调用==操作符。子类不可以重写该方法。
public final boolean equals(Object other) {
return this==other;
}
// 返回该枚举常量的哈希码。和equals一致,该方法不可以被重写。
public final int hashCode() {
return super.hashCode();
}
// 因为枚举常量是单例的,所以不允许克隆。
protected final Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
// 比较该枚举常量和指定对象的大小。它们的类型要相同,根据它们在枚举声明中的先后顺序来返回大小(前面的小,后面的大)。子类不可以重写该方法
public final int compareTo(E o) {
Enum other = (Enum)o;
Enum self = this;
if (self.getClass() != other.getClass() && // optimization
self.getDeclaringClass() != other.getDeclaringClass())
throw new ClassCastException();
return self.ordinal - other.ordinal;
}
// 得到枚举常量所属枚举类型的Class对象
public final Class<E> getDeclaringClass() {
Class clazz = getClass();
Class zuper = clazz.getSuperclass();
return (zuper == Enum.class) ? clazz : zuper;
}
// 返回带指定名称的指定枚举类型的枚举常量。名称必须与在此类型中声明枚举常量所用的标识符完全匹配。不允许使用额外的空白字符。
public static <T extends Enum<T>> T valueOf(Class<T> enumType,
String name) {
T result = enumType.enumConstantDirectory().get(name);
if (result != null)
return result;
if (name == null)
throw new NullPointerException("Name is null");
throw new IllegalArgumentException(
"No enum const " + enumType +"." + name);
}
// 不允许反序列化枚举对象
private void readObject(ObjectInputStream in) throws IOException,
ClassNotFoundException {
throw new InvalidObjectException("can't deserialize enum");
}
// 不允许反序列化枚举对象
private void readObjectNoData() throws ObjectStreamException {
throw new InvalidObjectException("can't deserialize enum");
}
// 枚举类不可以有finalize方法,子类不可以重写该方法
protected final void finalize() { }
}