枚举是JDK1.5的新加入的特性,Enum一般用来表示一组相同类型的常量,比如性别、日期、月份、颜色等。对这些属性用常量的好处是显而易见的,不仅可以保证单例,且做比较运算的时候可以用==来替换equals。

当我们在编写源代码的时候需要让某个类型的变量的取值缩小在一个人为控制的范围内时,枚举就可以在这个时候大显身手了,否则编译器就会报错。枚举可以让编译器在编译就可以控制程序中编写的非法值,普通变量的方式在开发阶段无法实现这一目标。这里我们使用定义星期的枚举来演示一下,感受一下使用枚举给我们编程带来的方便之处:



public class EnumTest {
	public static void main(String[] args) {
		//由于构造方法私有化,所以这里并不能直接new创建一个Weekday对象,必须指定到定义好的对象(限定了定义范围)
		Weekday monday = Weekday.MON;
		//枚举在定义的时候直接强制继承了java.lang.Enum,由于Java不支持多继承,所以只能实现接口类扩展
		System.out.println("monday.nextDay() :" + monday.nextDay());
		//获取monday的值
		System.out.println("monday.getValue() :" + monday.getValue());
	}
	
	enum Weekday {
		SUN {
			public Weekday nextDay() {
				return MON;
			}
		},
		MON {
			public Weekday nextDay() {
				return TUE;
			}
		},
		TUE {
			public Weekday nextDay() {
				return WED;
			}
		},
		WED {
			public Weekday nextDay() {
				return THI;
			}
		},
		THI {
			public Weekday nextDay() {
				return FRI;
			}
		},
		FRI {
			public Weekday nextDay() {
				return SAT;
			}
		},
		SAT {
			public Weekday nextDay() {
				return SUN;
			}
		};
		//构造方法必须申明为私有private
		private Weekday() {}
		//注意在枚举声明中枚举常量列表要在声明内容的最前面,
		// 若后面还有其他内容(方法等),则列表后要加分号区分开来,
		// 若没有其他内容可以不加,但鉴于编码习惯,提倡还是随手加上分号
		public abstract Weekday nextDay();
		public int getValue() {
			return this.ordinal();
			//这里直接使用了ordinal方法返回其在枚举声明中的序数,其中初始常量序数为零
			//即这里从SUN到SAT值分别为0-6
		}
	}
}

 

通过上面的简单实例我们可以看到在某些情况下使用枚举会增强程序的健壮性、可维护性,然而有时候使用枚举还可以增强程序安全性直接在编译的时候告知程序员错误,减少不少的开销,特别是应用于switch方法参数时效果尤其明显,我们还是通过一个例子感受一下通过枚举优化的switch方法前后的不同之处:

class EnumTest2 {
	public static void main(String[] args) {
		printColor(1);
		printColor(2);
		printColor(3);
		printColor(4);
	}
	public static void printColor(int color) {
		switch(color) {
			case 1:
				System.out.println("这是红色");
				break;
			case 2:
				System.out.println("这是绿色");
				break;
			case 3:
				System.out.println("这是黑色");
				break;
			default:
				System.out.println("未知颜色");
		}
	}
}

上面的printColor方法虽然完成了我们对程序的基本要求,但是如果在调用方法时传入了其他参数比如4,那么就没有意义,并且调用者不知道为何如此,如果此时程序还是接着运行非常危险,所以我们有义务告诉调用者发生了什么导致上面的情况。

default:
				throw new ColorTypeException("未知颜色!");

将default语句修改成这样并声明一个颜色异常类在传入错误参数的时候告知调用者,
上面的方法有所改进,让调用者知道自己犯了什么样的错误,增强了安全性,但是还不够。
我们可以想想printColor这样单纯的方法在内部还要做一些入参判断和异常处理,如此一来给程序增加了负荷。
我们能不能想到一种方法在传入参数的源头就对参数进行一下约束,压根就不让错误的参数传进来呢?当然可以,下面就来看看运用枚举的优化方案是怎样的

class EnumTest2 {
	public static void main(String[] args) {
		Color red = Color.RED;
		Color green = Color.GREEN;
		Color black = Color.BLACK;
		
		printColor(red);
		printColor(green);
		printColor(black);
		
		// Color other = Color.WHITE;
		// printColor(other);
		// 上面语句编译报错,通过枚举直接在向方法导入参数的时候严格限定了范围,也就不需要default语句了
	}
	public static void printColor(Color color) {
		switch(color) {
			case RED:
				System.out.println("这是红色");
				break;
			case GREEN:
				System.out.println("这是绿色");
				break;
			case BLACK:
				System.out.println("这是黑色");	
				break;
		}
	}

	enum Color {
		RED,GREEN,BLACK;
	}
}

 

使用枚举之后我们发现在真正意义上对入参进行了范围控制,并且在编译的时候就可以发现错误,大大节省了成本。

当然,使用枚举带来的便利还远远不止这些,上面只是冰山一角,我们在程序开发时,需要考虑各种各样的实现方法并从中选择最优者,这是一项非常重要的技能。优秀的程序员不会满足于临时解决方案。