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。