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