在JDK 1.5之前通常用final来定义各种常量,现在新加了枚举类型,最简单的用法如下:
enum Color { RED, GREEN }
还可以像普通的类那样自己定义属性和方法:
enum Color { RED("red"), GREEN("green"); String name; Color(String name) { this.name = name; } public String toString(){ return name; } }
甚至enum还可以去实现接口:
enum Color implements Comparable<Color> { RED, GREEN; }
在使用的时候,枚举可以用来比较:
Color c = Color.RED; if(c == Color.GREEN){ // ... }
也可以用来switch:
Color c = Color.RED; switch (c) { case RED: case GREEN: }
而且你可以很方便的变量一个枚举类型中所有的属性:
for (Color c : Color.values()) { System.out.println(c); }
甚至在你只知道枚举的变量名的时候也能拿到对应的属性:
System.out.println(Color.valueOf("RED"));
看下来,枚举在定义常量上面做了不少友好的封装。
首先不同的枚举类是不同的类型,而你用final static修饰的一般都是int等基本类型,这样很难做类型检查,这算是Enum比较大的一个优势的优势,在写代码的时候不会传错参数:
public static void check(Color c){ }
当你传入其他类型参数时会编译出错。
在编译之后会有一个Color.class文件,使用javap查看:
final class Color extends java.lang.Enum implements java.lang.Comparable{ public static final Color RED; public static final Color GREEN; public static Color[] values(); public static Color valueOf(java.lang.String); static {}; }
该类继承自java.lang.Enum,然后通过javap -c Color来看初始化的代码:
static {}; Code: 0: new #4; //class Color 3: dup 4: ldc #7; //String RED 6: iconst_0 7: invokespecial #8; //Method "<init>":(Ljava/lang/String;I)V 10: putstatic #9; //Field RED:LColor; 13: new #4; //class Color 16: dup 17: ldc #10; //String GREEN 19: iconst_1 20: invokespecial #8; //Method "<init>":(Ljava/lang/String;I)V 23: putstatic #11; //Field GREEN:LColor; 26: iconst_2 27: anewarray #4; //class Color 30: dup 31: iconst_0 32: getstatic #9; //Field RED:LColor; 35: aastore 36: dup 37: iconst_1 38: getstatic #11; //Field GREEN:LColor; 41: aastore 42: putstatic #1; //Field $VALUES:[LColor; 45: return
这里大家可能会对枚举switch有疑问,我们写代码来看下:
public class Test { public void func(Color c){ switch(c){ case RED: case GREEN: } } }
然后用javap -c查看,得到:
public void func(Color); Code: 0: getstatic #2; //Field Test$1.$SwitchMap$Color:[I 3: aload_1 4: invokevirtual #3; //Method Color.ordinal:()I 7: iaload 8: lookupswitch{ //2 1: 36; 2: 36; default: 36 } 36: return }
可以看到这里switch的其实还是enum类中的ordinal(int),和之前我们对switch的认识是一致的。