Java enum的用法详解

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

 

你可能感兴趣的:(enum,枚举)