首页 > 代码库 > [Java]枚举

[Java]枚举

用法

在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"));
看下来,枚举在定义常量上面的作用还真大。

枚举VS常量

首先不同的枚举类是不同的类型,而你用final static修饰的一般都是int等基本类型,这样的常量不容易做到类型检查,这也算是一个枚举的优势:
    public static void check(Color c){
        
    }
如果你想封装一种类型的常量类型检查的话(除非有现成的类),为什么不用enum?

enum到底是什么

在编译之后会有一个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的认识是一致的。

----------END----------