Java中枚举实现的分析:
示例:
public static enum SEVERITY{
INFO,WARN,ERROR
}
enum很像特殊的class,实际上enum声明定义的类型就是一个类。 而这些类都是类库中Enum类的子类(java.lang.Enum<E>)。它们继承了这个Enum中的许多有用的方法。我们对代码编译之后发现,编译器将enum类型单独编译成了一个字节码文件:SEVERITY.class。
SEVERITY字节码代码
// Signature: Ljava/lang/Enum<LSEVERITY;>;
public final enum SEVERITY {
// Field descriptor #6 LSEVERITY;
public static final enum SEVERITY INFO;
// Field descriptor #6 LSEVERITY;
public static final enum SEVERITY WARN;
// Field descriptor #6 LSEVERITY;
public static final enum SEVERITY ERROR;
// Field descriptor #10 [LSEVERITY;
private static final synthetic SEVERITY[] ENUM$VALUES;
// Method descriptor #12 ()V
// Stack: 4, Locals: 0
static {};
0 new SEVERITY [1]
3 dup
4 ldc <String "INFO"> [14]
6 iconst_0
7 invokespecial SEVERITY(java.lang.String, int) [15]
10 putstatic SEVERITY.INFO : SEVERITY [19]
13 new SEVERITY [1]
16 dup
17 ldc <String "WARN"> [21]
19 iconst_1
20 invokespecial SEVERITY(java.lang.String, int) [15]
23 putstatic SEVERITY.WARN : SEVERITY [22]
26 new SEVERITY [1]
29 dup
30 ldc <String "ERROR"> [24]
32 iconst_2
33 invokespecial SEVERITY(java.lang.String, int) [15]
36 putstatic SEVERITY.ERROR : SEVERITY [25]
39 iconst_3
40 anewarray SEVERITY [1]
43 dup
44 iconst_0
45 getstatic SEVERITY.INFO : SEVERITY [19]
48 aastore
49 dup
50 iconst_1
51 getstatic SEVERITY.WARN : SEVERITY [22]
54 aastore
55 dup
56 iconst_2
57 getstatic SEVERITY.ERROR : SEVERITY [25]
60 aastore
61 putstatic SEVERITY.ENUM$VALUES : SEVERITY[] [27]
64 return
Line numbers:
[pc: 0, line: 4]
[pc: 39, line: 2]
// Method descriptor #18 (Ljava/lang/String;I)V
// Stack: 3, Locals: 3
private SEVERITY(java.lang.String arg0, int arg1);
0 aload_0 [this]
1 aload_1 [arg0]
2 iload_2 [arg1]
3 invokespecial java.lang.Enum(java.lang.String, int) [31]
6 return
Line numbers:
[pc: 0, line: 2]
Local variable table:
[pc: 0, pc: 7] local: this index: 0 type: SEVERITY
// Method descriptor #34 ()[LSEVERITY;
// Stack: 5, Locals: 3
public static SEVERITY[] values();
0 getstatic SEVERITY.ENUM$VALUES : SEVERITY[] [27]
3 dup
4 astore_0
5 iconst_0
6 aload_0
7 arraylength
8 dup
9 istore_1
10 anewarray SEVERITY [1]
13 dup
14 astore_2
15 iconst_0
16 iload_1
17 invokestatic java.lang.System.arraycopy(java.lang.Object, int, java.lang.Object, int, int) : void [35]
20 aload_2
21 areturn
Line numbers:
[pc: 0, line: 1]
// Method descriptor #42 (Ljava/lang/String;)LSEVERITY;
// Stack: 2, Locals: 1
public static SEVERITY valueOf(java.lang.String arg0);
0 ldc <Class SEVERITY> [1]
2 aload_0 [arg0]
3 invokestatic java.lang.Enum.valueOf(java.lang.Class, java.lang.String) : java.lang.Enum [43]
6 checkcast SEVERITY [1]
9 areturn
Line numbers:
[pc: 0, line: 1]
}
不难看出所有的枚举值都是类静态常量。
下面介绍enum的定义及用法
1、SEVERITY枚举类是一个class,而且是一个不可以被继承的final类。其枚举值(INFO,WARN,ERROR)都是SEVERITY类中静态常量, 我们可以通过下面的方式来得到SEVERITY枚举类的一个实例:
SEVERITY s = SEVERITY.INFO;
注意:这些枚举值都是public static final的,也就是我们经常所定义的常量方式,因此枚举类中的枚举值最好全部大写。
2、因为枚举类是class,所以在枚举类型中有构造器,方法和数据域。但是枚举类的构造器有点不同:
public enum SEVERITY
{
INFO("info"), WARN("warn"), ERROR("error");
private SEVERITY(String code)
{
this.code = code;
}
public String toString()
{
return "(" + code + ")";
}
private String code;
public String getCode()
{
return code;
}
public void setCode(String code)
{
this.code = code;
}
}
构造器只能私有(private),绝对不允许有public构造器。 这样可以保证外部代码无法新构造枚举类的实例。因为枚举值是public static final的常量。 但枚举类的方法和数据域可以允许外部访问。
3、所有枚举类都继承了Enum的方法,下面介绍这些方法:
(1) ordinal()方法: 返回枚举值在枚举类中的顺序,这个顺序根据枚举值声明的顺序而定。
SEVERITY.INFO.ordinal(); //返回结果:0
(2) compareTo()方法: Enum实现了java.lang.Comparable接口,因此可以比较对象与指定对象的顺序。Enum中的compareTo返回的是两个枚举值的顺序之差。当然,前提是两个枚举值必须属于同一个枚举类,否则会抛出ClassCastException()异常。
SEVERITY.INFO.compareTo(SEVERITY.WARN); //返回结果 -1
(3) values()方法: 静态方法,返回一个包含全部枚举值的数组。
SEVERITY[] s=SEVERITY.values();
(4) valueOf()方法: 返回带指定名称的指定枚举类型的枚举常量。
SEVERITY.valueOf("ERROR"); //返回结果: SEVERITY.ERROR
(5) equals()方法: 比较两个枚举类对象的引用。
4、枚举类可以在switch语句中使用。
SEVERITY severity =SEVERITY.ERROR;
switch(severity){
case INFO: System.out.println("it's info");break;
case WARN: System.out.println("it's warn");break;
case ERROR: System.out.println("it's error");break;
}
5、实现接口
所有的枚举都继承自java.lang.Enum类。由于Java 不支持多继承,所以枚举对象不能再继承其他类。
public interface Behaviour {
void print();
String getInfo();
}
public enum Color implements Behaviour {
RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);
// 成员变量
private String name;
private int index;
// 构造方法
private Color(String name, int index) {
this.name = name;
this.index = index;
}
// 接口方法
@Override
public String getInfo() {
return this.name;
}
// 接口方法
@Override
public void print() {
System.out.println(this.index + ":" + this.name);
}
}
6、使用接口组织枚举
public interface Food {
enum Coffee implements Food {
BLACK_COFFEE, DECAF_COFFEE, LATTE, CAPPUCCINO
}
enum Dessert implements Food {
FRUIT, CAKE, GELATO
}
}
7、关于枚举集合的使用
java.util.EnumSet和java.util.EnumMap是两个枚举集合。EnumSet保证集合中的元素不重复;EnumMap中的 key是enum类型,而value则可以是任意类型。
public class LightTest {
// 1.定义枚举类型
public enum Light {
// 利用构造函数传参
RED(1), GREEN(3), YELLOW(2);
// 定义私有变量
private int nCode;
// 构造函数,枚举类型只能为私有
private Light(int _nCode) {
this.nCode = _nCode;
}
@Override
public String toString() {
return String.valueOf(this.nCode);
}
}
/**
*
* @param args
*/
public static void main(String[] args) {
// 1.遍历枚举类型
System.out.println("演示枚举类型的遍历 ......");
testTraversalEnum();
// 2.演示EnumMap对象的使用
System.out.println("演示EnmuMap对象的使用和遍历.....");
testEnumMap();
// 3.演示EnmuSet的使用
System.out.println("演示EnmuSet对象的使用和遍历.....");
testEnumSet();
}
/**
*
* 演示枚举类型的遍历
*/
private static void testTraversalEnum() {
Light[] allLight = Light.values();
for (Light aLight : allLight) {
System.out.println("当前灯name:" + aLight.name());
System.out.println("当前灯ordinal:" + aLight.ordinal());
System.out.println("当前灯:" + aLight);
}
}
/**
*
* 演示EnumMap的使用,EnumMap跟HashMap的使用差不多,只不过key要是枚举类型
*/
private static void testEnumMap() {
// 1.演示定义EnumMap对象,EnumMap对象的构造函数需要参数传入,默认是key的类的类型
EnumMap<Light, String> currEnumMap = new EnumMap<Light, String>(
Light.class);
currEnumMap.put(Light.RED, "红灯");
currEnumMap.put(Light.GREEN, "绿灯");
currEnumMap.put(Light.YELLOW, "黄灯");
// 2.遍历对象
for (Light aLight : Light.values()) {
System.out.println("[key=" + aLight.name() + ",value="
+ currEnumMap.get(aLight) + "]");
}
}
/**
*
* 演示EnumSet如何使用,EnumSet是一个抽象类,获取一个类型的枚举类型内容<BR/>
*
* 可以使用allOf方法
*/
private static void testEnumSet() {
EnumSet<Light> currEnumSet = EnumSet.allOf(Light.class);
for (Light aLightSetElement : currEnumSet) {
System.out.println("当前EnumSet中数据为:" + aLightSetElement);
}
}
}
转载请注明出处:http://xieke90.iteye.com/blog/2224034