枚举是指将变量的值一一列举出来,变量的值只限于列举出的范围
如,一周只有7天,一年只有12个月
与单例模式不同的是,枚举中可以有一个以上的实例

模拟枚举

首先将自定义枚举类的构造私有化
然后创建若干静态常量对象供外界访问
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Direction {
public static final Direction FRONT = new Direction("前");
public static final Direction BEHIND = new Direction("后");
public static final Direction LEFT = new Direction("左");
public static final Direction RIGHT = new Direction("右");
private String name;
private Direction(String name){this.name = name;}
public String getName() {return name;}
}
public static void main(String[] args) {
Direction front = Direction.FRONT;
System.out.println(front);
System.out.println(front.getName());
Direction behind = Direction.BEHIND;
System.out.println(behind.getName());
Direction left = Direction.LEFT;
System.out.println(left.getName());
Direction right = Direction.RIGHT;
System.out.println(right.getName());
}
执行结果如下 :

枚举

若自己定义枚举,其实是很麻烦的
在JDK5,java为我们提供了枚举类
格式为 :
    public enum 枚举类名{
        枚举项1,枚举项2,..;
    }
简单的实例如下 :
1
2
3
4
5
6
7
public enum Enum01 {
FRONT,BEHIND,LEFT,RIGHT;
}
public static void main(String[] args) {
Enum01 enum01 = Enum01.FRONT;
System.out.println(enum01);
}
可以看到打印的是枚举实例的名字
结果如下 :

为什么会产生这样的结果呢?
其实枚举是java为我们作了封装
省去了我们自己创建枚举的设计过程
使得代码更加简洁,打开枚举的字节码文件
可以发现,需要了解枚举类才行
结果如下 : 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// Decompiled by Jad v1.5.8e2. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://kpdus.tripod.com/jad.html
// Decompiler options: packimports(3) fieldsfirst ansi space
// Source File Name: Enum01.java
package cn._03_enum;

public final class Enum01 extends Enum{
public static final Enum01 FRONT;
public static final Enum01 BEHIND;
public static final Enum01 LEFT;
public static final Enum01 RIGHT;
private static final Enum01 $VALUES[];

public static Enum01[] values(){
return (Enum01[])$VALUES.clone();
}
public static Enum01 valueOf(String name){
return (Enum01)Enum.valueOf(cn/_03_enum/Enum01, name);
}
private Enum01(String s, int i){super(s, i);}
static
{
FRONT = new Enum01("FRONT", 0);
BEHIND = new Enum01("BEHIND", 1);
LEFT = new Enum01("LEFT", 2);
RIGHT = new Enum01("RIGHT", 3);
$VALUES = (new Enum01[] {
FRONT, BEHIND, LEFT, RIGHT
});
}
}

Enum<E extends Enum>类

该类是所有Java语言枚举类型的公共基本类
1
2
public abstract class Enum<E extends Enum<E>>
extends Objectimplements Comparable<E>, Serializable

构造方法

单独的构造方法,用于响应枚举类型声明的编译器发出的代码
1
protected Enum(String name, int ordinal)
需要知道的是 classes是无法直接继承Enum类的

成员方法

枚举类无法克隆,重写了Cloneable的clone方法
直接抛出CloneNotSupportedException
1
2
3
protected final Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
public final int compareTo(E o)
比较枚举的序号,也就是元素的位置
通过class文件解析也发现了,第一个元素为0...n
1
2
3
4
5
6
7
8
public final int compareTo(E o) {
Enum<?> other = (Enum<?>)o;
Enum<E> self = this;
if (self.getClass() != other.getClass() && // optimization
self.getDeclaringClass() != other.getDeclaringClass())
throw new ClassCastException();
return self.ordinal - other.ordinal;
}
equals方法对Object作了重写
但是也是比较的内存地址
1
2
3
public final boolean equals(Object other) {
return this==other;
}
枚举类是不能有finalize方法的
1
protected final void finalize() { }
getDeclaringClass获取声明的枚举类型
判断两个枚举常量是否类型一致的时候
若它们同时继承自枚举类,则返回其枚举类型
若继承自枚举类的一个子类,则返回其父类
1
2
3
4
5
public final Class<E> getDeclaringClass() {
Class<?> clazz = getClass();
Class<?> zuper = clazz.getSuperclass();
return (zuper == Enum.class) ? (Class<E>)clazz : (Class<E>)zuper;
}
这主要针对的是枚举类可能出现的匿名内部类的情况
简单的案例测试如下 :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public  enum  Cat{
WHITH(){
@Override
public void fun() {System.out.println("白喵,喵喵~");}
},BLACK;
public void fun(){System.out.println("喵喵~");}
}
public enum Dog {
WHITH,BLACK;
}
public static void main(String[] args) {
Class c1 = Cat.BLACK.getDeclaringClass();
Class d1 = Dog.BLACK.getDeclaringClass();
System.out.println(c1 == d1);

Class c2 = Cat.WHITH.getDeclaringClass();
Class d2 = Dog.WHITH.getDeclaringClass();
System.out.println(c1 == c2);
System.out.println(d1 == d2);
}
执行结果如下 :

hashCode方法就是Object的,返回内存地址的哈希值
name方法返回枚举常量的名称与toString一样
1
2
3
4
5
6
public final String name() {
return name;
}
public String toString() {
return name;
}
ordinal方法返回该常量在这个枚举类型中的序数
1
2
3
public final int ordinal() {
return ordinal;
}
valueOf方法通过枚举字节码对象以及名称获取该常量
1
2
3
4
5
6
7
8
9
public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) {
T result = enumType.enumConstantDirectory().get(name);
if (result != null)
return result;
if (name == null)
throw new NullPointerException("Name is null");
throw new IllegalArgumentException(
"No enum constant " + enumType.getCanonicalName() + "." + name);
}
仍然沿用猫的枚举类,调用其fun方法
可以发现打印出  白喵,喵喵~
简单案例如下 :
1
2
3
public static void main(String[] args){
Enum.valueOf(Cat.class,"WHITH").fun();
}