ENUM类详解
在单例模式的时候,有一种写法就是利用enum类的特性:每个实例只会被JVM加载一次;
但是由于之前对enum类了解的并不多,尤其是定义实例的方式不同,为什么一个字段就是enum的实例?为什么每个实例只会被加载一次?
其实要了解enum类最简单的方法就是反编译看源码!
话不多说,上代码~
这是一个简单的enum类:
public enum TestEnum {
YELLOW,RED,BLUE,BLACK
}
反编译这个类,用Jdk自带的工具:javap -verbose TestEnum.class(class文件的路径,在TestEnum.class同一路径打开命令行窗口直接这样写就可以,不在同一路径记得补全路径)
public final class design.TestEnum extends java.lang.Enum<design.TestEnum>
......//此处省略掉一些看不懂的代码,对理解enum影响不大,有兴趣的同学可以自己反编译看下
......
{
public static final design.TestEnum YELLOW;
descriptor: Ldesign/TestEnum;
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
public static final design.TestEnum RED;
descriptor: Ldesign/TestEnum;
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
public static final design.TestEnum BLUE;
descriptor: Ldesign/TestEnum;
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
public static final design.TestEnum BLACK;
descriptor: Ldesign/TestEnum;
flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUM
//此处省略掉一些看不懂的代码,对理解enum影响不大,有兴趣的同学可以自己反编译看下
...
....
..
Ljava/lang/Enum<Ldesign/TestEnum;>;
SourceFile: "TestEnum.java"
看到这些代码,之前我们的疑惑瞬间解开;为什么YELLOW是enum的实例?为什么enum类的实例只会被加载一次??看代码一目了然:
YELLOW,RED,BLUE,BLACK
public static final design.TestEnum YELLOW;
public static final design.TestEnum RED;
public static final design.TestEnum BLUE;
public static final design.TestEnum BLACK;
问题解决!
我们再来深入的了解一下,这个enum类;
首先看看:
public final class design.TestEnum extends java.lang.Enum<design.TestEnum>
有一个小特性:被final修饰,说明enum类不能被继承;
既然enum类本质也是一个class那我们能不能创建构造方法呢?能不能创建字段?能不能创建方法??
答案是肯定滴!
enum类中
- 可以创建构造方法
- 可以定义字段
- 可以创建方法
不过要注意一点:构造方法只能用private修饰或者不用修饰符
YELLOW(12,"yellow11"),
RED(13,"red12"),
BLUE(14,"blue13"),
BLACK(15,"black14");
//自定义变量val,name;
public int val;
public String name;
//自定义构造方法,前面只能用private修饰,或者不写
TestEnum(int val,String name){
this.val = val;
this.name = name;
}
//自定义方法
public int getVal(){
return val;
}
看到上面代码我们知道所有的enum类都是继承了Enum;
再看下Enum源码:其中有2个属性
/**
* The name of this enum constant, as declared in the enum declaration.
* Most programmers should use the {@link #toString} method rather than
* accessing this field.
*/
private final String name;
//获取name属性
public final String name() {
return name;
}
/**
* The ordinal of this enumeration constant (its position
* in the enum declaration, where the initial constant is assigned
* an ordinal of zero).
*
* Most programmers will have no use for this field. It is designed
* for use by sophisticated enum-based data structures, such as
* {@link java.util.EnumSet} and {@link java.util.EnumMap}.
*/
private final int ordinal;
//获取ordinal属性
public final int ordinal() { return ordinal;}
name,就是实例的名称 ,比如实例YELLOW,他的name就是:String型的:YELLOW;
ordinal,是实例的下标,从0开始跟数组一样;比如上面4个实例
:YELLOW,RED,BLUE,BLACK;他们的下表分别是:0,1,2,3;是按照他们的先后顺序来确定的;
看到这,大概对enum就有一个比较清楚的认识了;