您的位置:首页 > 编程语言 > Java开发

java之类型安全的枚举

2014-02-25 21:53 597 查看

why

  枚举,顾名思义,就是一组可罗列的值,如四季春夏秋冬,方位东南西北,星期,月份等。在J2SE5.0 Tiger会出现之前,通常定义一个普通类或者抽象类,在类中定义一组public staic final 修饰的成员变量来表示这样的数据。

public abstract class Direction {
public static final int EAST = 0;  //东
public static final int WEST = 1;  //西
public static final int SOUTH = 2;  //南
public static final int NORTH = 3;  //北
}


然后我们就能通过“类名.变量名“Direction.EAST的形式来使用这些常量。

  那么像这样定义有什么不好的地方呢?我就举个例子来说明,比如有一个方法,需要接收上述的参数,那方法的声明肯定就像这样 returnType methodName(int direction); 注意方法的参数是int型,即任何的int类型的值不限0、1、2、3都能够作为该方法的参数。为了避免意料之外的结果,必须限定参数的上限和下限,否则就容易误传入非正确的int值,编译器是检查不出这类错误的,全靠人为控制。另一方面,使用静态常量时候,常常不够直观,不看定义,谁也不知道0、1、2、3究竟表示什么,而且当有要罗列多少种方向的需求的时候,也不方便。

  J2SE5.0提供了解决上述问题的一种方式,即用关键字enum定义的枚举。它克服了静态常量表示法的不足,在编译的时候,编译器就能检查出非法的参数,并不需要设定程序的上下界,所以说枚举是类型安全的。而且通过它自带的方法,很容易罗列所表示的值,简单明了。

what

  那么枚举如何表示上述的方向呢?

public enum Direction{
EAST,WEST,SOUTH,NORTH;
}


  上面代码就是java枚举的定义。枚举本质上还是一个类,是和class,interface,annotation是一个级别的,源文件编译之后还是一个字节码文件,表面上我们用关键字enum定义,看不出什么,实际上编译器帮我们完成了大部分的东西。可以通过反编译工具把字节码文件反编译过来,就能看到编译器做了什么事。

  所有枚举类型都继承自Enum,Enum是所有枚举类型的基类。这个继承是编译器帮我们完成的。 因为枚举已经继承了Enum,所以不能再继承别的类,可以实现接口。枚举的构造函数只能是private或者默认修饰符,所以在编译完成,究竟有哪些枚举实例已经固定了。

how

带构造函数的枚举,这个例子也说明枚举可以添加成员变量和方法

public enum Direction {
EAST("东"), WEST("西"), SOUTH("南"), NORTH("北");

private final String name;

private Direction(String name) {
this.name = name;
}

public String getName() {
return name;
}
}


实现接口的枚举

public enum Direction implements MyService {
EAST, WEST, SOUTH, NORTH;

public void doSomething() {
System.out.println(this.name());
}
}

interface MyService {
public void doSomething();
}


枚举(重写父类方法)

public enum Direction {
EAST {
public void doSomething() {
System.out.println("东");
}
},
WEST {
public void doSomething() {
System.out.println("西");
}
},
SOUTH {
public void doSomething() {
System.out.println("南");
}
},
NORTH;

public void doSomething() {
System.out.println(this.name());
}
}


枚举(实现抽象方法)

public enum Direction {
EAST {
@Override
void doSomething() {
System.out.println("east");
}
},
WEST {
@Override
void doSomething() {
System.out.println("west");
}

},
SOUTH {
@Override
void doSomething() {
System.out.println("south");
}
},
NORTH {
@Override
void doSomething() {
System.out.println("north");
}
};

abstract void doSomething();
}


  枚举比较

Direction direction = Direction.EAST;
System.out.println(direction.compareTo(Direction.WEST));

// if语句中的使用
if (Direction.EAST == direction) {
System.out.println("equal");
} else
System.out.println("not equal");

// 可以用于switch语句
switch (direction) {
case WEST:
System.out.println("west");
break;
case EAST:
System.out.println("east");
break;
case SOUTH:
System.out.println("south");
break;
case NORTH:
System.out.println("north");
break;
default:
System.out.println("default");
}


  至于枚举类从父类继承来的方法,请自行查阅java api帮助文档。枚举的出现,也在java集合框架中添加了两个成员,EnumSet和EnumMap,即枚举集合和枚举映射。EnumSet是一个抽象类,里面定义了创建枚举集合的不同静态方法,具体的用法看api,与普通的set和map无异。

  如果想了解更多的内容,请看这篇文章http://www.iteye.com/topic/678381
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: