Java基础:枚举Enum

时间:2015-01-30 17:52:40   收藏:0   阅读:140

在某些情况下,一个类的对象是有限而且固定的,比如季节类,它只有4个对象:春、夏、秋、冬。这种实例有限而且固定的类,在Java里被称为枚举类。

1 手动实现枚举类

示例:

package com.demo2;

public class Season {

	public static final Season SPRING = new Season("春天", "趁春踏青");
	public static final Season SUMMER = new Season("夏天", "夏日炎炎");
	public static final Season FALL = new Season("秋天", "秋高气爽");
	public static final Season WINTER = new Season("冬天", "围炉观雪");

	public static Season getSeason(int seasonNum) {

		switch (seasonNum) {
		case 1:
			return SPRING;
		case 2:
			return SUMMER;
		case 3:
			return FALL;
		case 4:
			return WINTER;
		default:
			return null;
		}

	}

	private final String name;
	private final String desc;

	private Season(String name, String desc) {
		this.name = name;
		this.desc = desc;
	}

	public String getName() {
		return name;
	}

	public String getDesc() {
		return desc;
	}
}
package com.demo2;

public class Test2 {
	public Test2(Season s) {
		System.out.println(s.getName() + "-----" + s.getDesc());
	}

	public static void main(String[] args) {
		new Test2(Season.SPRING);
	}
}

如果需要手动实现枚举,可以采用如下设计方式:

PS:有些程序员喜欢使用简单地定义几个静态常量来表示枚举类。

例如:

public static final int SEASON_SPRING=1;
public static final int SEASON_SUMMER=2;
public static final int SEASON_FALL=3;
public static final int SEASON_WINTER=4;

这种方式存在几个问题:

2 枚举类Enum

JDK 5新增了一个关键字Enum,它与class,interface的地位相同,用来定义枚举类。枚举类其实是一个特殊的类,它可以有自己的Field,方法,构造函数,可以实现一个或多个接口。

2.1 定义枚举类

示例:

package com.demo2;

public enum SeasonEnum{
	SPRING, SUMMER, FALL, WINTER;
}

编译该段代码,将生成一个SeasonEnum.class文件,说明枚举类是一种特殊的类。

定义枚举类时,需要显式地列出所有的枚举值,例如上面的SPRING, SUMMER, FALL, WINTER;所示,所有的枚举值之间以英文逗号(,)隔开,枚举值列举结束后,以英文分号作为结束。这些枚举值代表了该枚举类的所有可能实例。

2.2 枚举类本质

将2.1中生成的SeasonEnum.class文件反编译:

javap -c SeasonEnum.class > SeasonEnum.txt

结果如下:

Compiled from "SeasonEnum.java"
public final class com.demo2.SeasonEnum extends java.lang.Enum<com.demo2.SeasonEnum> {
  public static final com.demo2.SeasonEnum SPRING;

  public static final com.demo2.SeasonEnum SUMMER;

  public static final com.demo2.SeasonEnum FALL;

  public static final com.demo2.SeasonEnum WINTER;

  static {};
    Code:
       0: new           #1     // class com/demo2/SeasonEnum
       3: dup           
       4: ldc           #15    // String SPRING
       6: iconst_0      
       7: invokespecial #16    // Method "<init>":(Ljava/lang/String;I)V
      10: putstatic     #20    // Field SPRING:Lcom/demo2/SeasonEnum;
      13: new           #1     // class com/demo2/SeasonEnum
      16: dup           
      17: ldc           #22    // String SUMMER
      19: iconst_1      
      20: invokespecial #16    // Method "<init>":(Ljava/lang/String;I)V
      23: putstatic     #23    // Field SUMMER:Lcom/demo2/SeasonEnum;
      26: new           #1     // class com/demo2/SeasonEnum
      29: dup           
      30: ldc           #25    // String FALL
      32: iconst_2      
      33: invokespecial #16    // Method "<init>":(Ljava/lang/String;I)V
      36: putstatic     #26    // Field FALL:Lcom/demo2/SeasonEnum;
      39: new           #1     // class com/demo2/SeasonEnum
      42: dup           
      43: ldc           #28    // String WINTER
      45: iconst_3      
      46: invokespecial #16    // Method "<init>":(Ljava/lang/String;I)V
      49: putstatic     #29    // Field WINTER:Lcom/demo2/SeasonEnum;
      52: iconst_4      
      53: anewarray     #1     // class com/demo2/SeasonEnum
      56: dup           
      57: iconst_0      
      58: getstatic     #20    // Field SPRING:Lcom/demo2/SeasonEnum;
      61: aastore       
      62: dup           
      63: iconst_1      
      64: getstatic     #23    // Field SUMMER:Lcom/demo2/SeasonEnum;
      67: aastore       
      68: dup           
      69: iconst_2      
      70: getstatic     #26    // Field FALL:Lcom/demo2/SeasonEnum;
      73: aastore       
      74: dup           
      75: iconst_3      
      76: getstatic     #29    // Field WINTER:Lcom/demo2/SeasonEnum;
      79: aastore       
      80: putstatic     #31    // Field ENUM$VALUES:[Lcom/demo2/SeasonEnum;
      83: return        

  public static com.demo2.SeasonEnum[] values();
    Code:
       0: getstatic     #31    // Field ENUM$VALUES:[Lcom/demo2/SeasonEnum;
       3: dup           
       4: astore_0      
       5: iconst_0      
       6: aload_0       
       7: arraylength   
       8: dup           
       9: istore_1      
      10: anewarray     #1     // class com/demo2/SeasonEnum
      13: dup           
      14: astore_2      
      15: iconst_0      
      16: iload_1       
      17: invokestatic  #39    // Method java/lang/System.arraycopy:(Ljava/lang/Object;ILjava/lang/Object;II)V
      20: aload_2       
      21: areturn       

  public static com.demo2.SeasonEnum valueOf(java.lang.String);
    Code:
       0: ldc           #1    // class com/demo2/SeasonEnum
       2: aload_0       
       3: invokestatic  #47   // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
       6: checkcast     #1    // class com/demo2/SeasonEnum
       9: areturn       
}

java.lang.Enum的源码结构如下:

技术分享

根据字节码和java.lang.Enum源码结构可以得出如下结论:

Java实现枚举的本质:

2.3 枚举类与switch结构

如果需要使用枚举类的某个实例,可以使用“枚举类.某个实例”的形式,例如SeasonEnum.SPRING。

示例:

package com.demo2;

public class Test {

	public static void judge(SeasonEnum s) {

		switch (s) {
		case SPRING:
			System.out.println("春天,趁春踏青");
			break;
		case SUMMER:
			System.out.println("夏天,夏日炎炎");
			break;
		case FALL:
			System.out.println("秋天,秋高气爽");
			break;
		case WINTER:
			System.out.println("冬天,围炉观雪");
			break;
		}

	}

	public static void main(String[] args) {
		judge(SeasonEnum.FALL);
	}
}

上面程序中的switch表达式中,使用了SeasonEnum对象作为表达式,这是JDK 5增加枚举后对switch的扩展:switch的控制表达式可以是任何枚举类型。不仅如此,当switch控制表达式使用枚举类型时,后面case表达式中的值直接使用枚举值名字,无须添加枚举类作为限定。



3 枚举类与构造函数


4 枚举类与接口



5 枚举类与抽象方法

待续








评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!