ITEEDU

Java Gossip: 简介列举型态

常数设置 中,您知道可以在类别(Class)或接口(Interface)中宣告常数加以管理,这只是让您存取与管理常数方便而已,来看看这个例子:

public void someMethod() {
	....
	doOp(OpConstants.TURN_RIGHT);
	....
}
public void doOp(int op) {
	switch(op) {
		case OpConstants.TURN_LEFT:
		System.out.println("向左转");
		break;
		case OpConstants.TURN_RIGHT:
		System.out.println("向右转");
		break;
		case OpConstants.SHOOT:
		System.out.println("射击");
		break;
	}
}

看来是不错,但doOp()方法接受的是int,您没有阻止粗心的程序设计人员对它输入OpConstants中规定外的其它常数,您也没有检查 switch中列举的值是不是正确的值,因为它骨子里就只是int而已。

当然您可以作一些检查,这需要一些额外的工作,如果您使用 J2SE 5.0,则这些额外的工作您不用亲自处理,使用列举型态(Enumerated Types)可以轻易的解决这些问题。

在J2SE 5.0中使用列举型态要使用"enum"关键词,以下先来看看列举型态的应用,举个实际的例子:

OpConstants.java
public enum OpConstants {TURN_LEFT, TURN_RIGHT, SHOOT}

不用怀疑,在OpConstants.java中写下以上的内容,然后用javac去编译它,虽然语法上不像,但列举型态骨子里就是一个类别,所以您编译完成后,会产生一个OpConstants.class档案。

来看下面这个例子了解如何使用定义好的列举型态:

Test.java
public class Test {
	public static void main(String[] args) {
		doOp(OpConstants.TURN_RIGHT);
	}
	public static void doOp(OpConstants opConstant) {
		switch(opConstant) {
			case TURN_LEFT:
			System.out.println("向左转");
			break;
			case TURN_RIGHT:
			System.out.println("向右转");
			break;
			case SHOOT:
			System.out.println("射击");
			break;
		}
	}
}

执行结果:

向右转

除了让您少打一些字之外,好像没有什么特别的,但如果您对doOp()方法输入其它的值,编译器会回报错误,因为doOp()所接受的是 OpConstants列举型态。

更进一步的,如果您在switch中加入了不属于OpConstants中列举的数值,编译器也会回报错误,例如:

....
public static void doOp(OpConstants opConstant) {
	switch(opConstant) {
		case TURN_LEFT:
		System.out.println("向左转");
		break;
		case TURN_RIGHT:
		System.out.println("向右转");
		break;
		case SHOOT:
		System.out.println("射击");
		break;
		case STOP:
		System.out.println("停止");
		break;
	}
}
....

编译器会替您作编译时期的检查,若检查出不属于OpConstant中的列举值,会显示以下的错误:

unqualified enumeration constant name required
case STOP:
^

您可以在一个独立的档案中宣告列举值,或是在某个类别中宣告列举成员,例如:

Test.java
public class Test {
	private enum OpConstant {TURN_LEFT, TURN_RIGHT, SHOOT};
	public static void doOp(OpConstant opConstant) {
		switch(opConstant) {
			case TURN_LEFT:
			System.out.println("向左转");
			break;
			case TURN_RIGHT:
			System.out.println("向右转");
			break;
			case SHOOT:
			System.out.println("射击");
			break;
		}
	}
	public static void main(String[] args) {
		doOp(OpConstant.TURN_LEFT);
	}
}

由于列举型态本质上还是个类别,所以这种方式有些像在宣告 内 部类别(Iinner class), 在您编译完Test.java档案后,除了Test.class之外,您会有一些额外的.class档案,在这个例子中就是Test$ OpConstants.class与Test$1.class,看到后两个档案,您就应该了解到这个程序的背后运作的有内部成员类别以及内部匿名类别。