夜光序言:
在父母的眼中,孩子常是自我的一部分,子女是他理想自我再来一次的机会~~
正文:枚举
1 什么是枚举类型
word文档的对齐方式有几种:左对齐、居中对齐、右对齐;
开车的方向有几种:前、后、左、右;
枚举就是有限实现个数的类型,你可能会说,byte类型也只有256个,没错,但我们真实定义为枚举的类型,一般最多也就十多个实例,再多就不会定义为枚举了。
2 JDK1.4之前的枚举类型
在JDK1.4之前没有枚举类型,都是使用int或字符串类型来表示枚举,如果枚举只有两个选项,那么连int都用不上,只需要使用boolean类型即可。
例如:BorderLayout类的方位给出五个:CENTER、
枚举与switch
1.5开始枚举类型可以在switch中使用!在1.7之后,String类型也可以放到switch中使用了。
Direction d = Direction.FRONT; switch(d) { case FRONT: System.out.println("前面");break; case BEHIND:System.out.println("后面");break; case LEFT: System.out.println("左面");break; case RIGHT: System.out.println("右面");break; default:System.out.println("错误的方向"); } Direction d1 = d; System.out.println(d1); |
夜光:注意,在switch中,不能使用枚举类名称,例如:“case Direction.FRONT:”这是错误的,因为编译器会根据switch中d的类型来判定每个枚举类型,在case中必须直接给出与d相同类型的枚举选项,而不能再有类型。
枚举类也是类
1 所有枚举类都是Enum的子类
所有枚举类都默认是Enum类的子类,无需我们使用extends来继承。这说明Enum中的方法所有枚举类都可以的。
- int compareTo(E e):比较两个枚举常量谁大谁小,其实比较的就是枚举常量在枚举类中声明的顺序,例如FRONT的下标为0,BEHIND下标为1,那么FRONT小于BEHIND;
- boolean equals(Object o):比较两个枚举常量是否相等;
- int hashCode():返回枚举常量的hashCode;
- String name():返回枚举常量的名字;
- int ordinal():返回枚举常量在枚举类中声明的序号,第一个枚举常量序号为0;
- String toString():把枚举常量转换成字符串;
- static T valueOf(Class enumType, String name):把字符串转换成枚举常量。
2 枚举类的构造器
枚举类也可以有构造器,构造器不能给出访问修饰,而且默认都是private构造器。因为枚举类的实例不能让外界来创建~~
enum Direction { FRONT, BEHIND, LEFT, RIGHT;
Direction() { System.out.println("hello"); } } |
3 枚举类的方法
再次强调,枚举类也是类,也可以有构造器、方法和属性,只是对构造器有一些限制而已。在语法上有一些怪异罢了~~
enum Direction { FRONT, BEHIND, LEFT, RIGHT; public void fun() { System.out.println("hello Enum!"); } } |
Direction.FRONT.fun(); |
4 枚举类的属性
枚举类也可以有属性。
但是,如果每个枚举常量的属性值如果都相同,那就失去了意义,我们需要让每个枚举常量的属性值不同,那么就需要自己使用构造器来创建枚举常量,然后在构造器中给每个枚举常量传递不同的值。
enum Direction { FRONT("前面"), BEHIND("后面"), LEFT("左面"), RIGHT("右面");
private String explain;
Direction(String explain) { this.explain = explain; }
public void setExplain(String explain) { this.explain = explain; }
public String getExplain() { return explain; } } |
String explain = Direction.FRONT.getExplain(); System.out.println(explain); |
5 使用匿名类来创建枚举常量
还可以使用匿名类来创建枚举常量,这说明枚举常量的类型是当前枚举类的子类,而且是个匿名类。
这可以让每个枚举常量有自己的类型,当然有自己的类型不是目的,而是有自己的行为才是目的~~
但是我们知道就算给匿名类添加了自己独有的方法,也是无法调用的,因为匿名类没有名字,只能使用父类的引用指向匿名类的实例,而多态之后只能调用父类中存在的方法。
所以,使用这种情况时,通常是为了让每个枚举常量重写当前枚举类中的方法(抽象方法)。
enum Direction { FRONT() { public void fun() { System.out.println("FROND:重写了fun()方法"); } }, BEHIND() { public void fun() { System.out.println("BEHIND:重写了fun()方法"); } }, LEFT() { public void fun() { System.out.println("LEFT:重写了fun()方法"); } }, RIGHT() { public void fun() { System.out.println("RIGHT:重写了fun()方法"); } };
public void fun() { System.out.println("没有意义的方法"); } } |
Direction.FRONT.fun(); Direction.BEHIND.fun(); Direction.LEFT.fun(); Direction.RIGHT.fun(); |
通常fun()方法应该定义为抽象的方法,因为每个枚举常量都会去重写它。
你无法把Direction声明为抽象类,但需要声明fun()方法为抽象方法。
enum Direction { FRONT() { public void fun() { System.out.println("FROND:重写了fun()方法"); } }, BEHIND() { public void fun() { System.out.println("BEHIND:重写了fun()方法"); } }, LEFT() { public void fun() { System.out.println("LEFT:重写了fun()方法"); } }, RIGHT() { public void fun() { System.out.println("RIGHT:重写了fun()方法"); } };
public abstract void fun(); } |
(。・∀・)ノ゙~~~枚举类的特殊方法
1 每个枚举类都有两个特殊方法
每个枚举类都有两个不用声明就可以调用的static方法,而且这两个方法不是父类中的方法。这又是枚举类特殊的地方,下面是Direction类的特殊方法。
- static Direction[] values():返回本类所有枚举常量;
- static Direction valueOf(String name):通过枚举常量的名字返回Direction常量,注意,这个方法与Enum类中的valueOf()方法的参数个数不同。
枚举的真实世界
1 枚举也是编译期状态
其实枚举也是编译期状态,在运行时JVM并不知道什么是枚举类型。这也就是说,编译器需要把枚举类型转换成普通类。
enum Direction {FRONT, BEHIND, LEFT, RIGHT} |
final class Direction extends Enum { public static final Direction FRONT; public static final Direction BEHIND; public static final Direction LEFT; public static final Direction RIGHT; private static final Direction ENUM$VALUES[];
static { FRONT = new Direction("FRONT", 0); BEHIND = new Direction("BEHIND", 1); LEFT = new Direction("LEFT", 2); RIGHT = new Direction("RIGHT", 3); ENUM$VALUES = new Direction[] {FRONT, BEHIND, LEFT, RIGHT}; }
private Direction(String s, int i) { super(s, i); }
public static Direction[] values() { Direction adirection[]; int i; Direction adirection1[]; System.arraycopy(adirection = ENUM$VALUES, 0, adirection1 = new Direction[i = adirection.length], 0, i); return adirection1; }
public static Direction valueOf(String s) { return (Direction) Enum.valueOf(Direction.class, s); } } |
EAST、SOUTH、WEST、NORTH。当使用容器类的方法添加组件时:add(new Button(), “CENTER”),这是合法的,但因为String类型太过宽泛,所以可能会出现add(new Button(), “哈哈”)的调用可能,这会导致运行时出现异常。
所以,JDK1.5又新增了枚举类型。
3 定义枚举类型
定义枚举类型需要使用enum关键字,例如:
public enum Direction { FRONT、BEHIND、LEFT、RIGHT; } |
Direction d = Direction.FRONT; |
注意,每个枚举选项之间是用逗号隔开的。如果枚举类没有构造器、方法等,在最后一个枚举选择后面可以不打分号。但是如果枚举类还有其他成员,那么就要在最后一个枚举项后面添加分号了。
Direction类型只有四个选项,你可以理解为这个枚举类只有四个实例对象一样。外界无法去创建新的枚举对象,只能从这四个中去选择。
其实大多数时候,我们使用枚举类型还是与以及使用int或String表示的枚举一样,基本上都是很简单的。