枚举类型详解
一.Enum详解
1.1枚举类型的介绍
JDK1.5加入了一个全新的类型的”类”—枚举类型,为此JDK1.5引入了一个新的关键字enum,我们可以这样定义一个枚举类型。
Demo:一个最简单的枚举类
public enum ColorType { RED, BLACK, YELLOW; }
运行结果
class Testenum { public static void main(String[] args) { System.out.println(ColorType.BLACK);//BLACK } }
遍历枚举ColorType的所有值
public static void main(String[] args) { //下面是for的增强循环方法,遍历枚举的所有值 for(ColorType color : ColorType.values()){ System.out.println(color);//RED BLACK YELLOW } }
1.2枚举类型的简单应用场景
描述一个人的状态:比如有以下状态SLEEP(睡觉),WORKING(工作),EATING(吃饭)
创建人的状态枚举类:
public enum PersonStatus { SLEEP,WORKING,EATING; }
打印出人的状态
public static void main(String[] args) { showStatus(PersonStatus.EATING); } public static void showStatus(PersonStatus status){ switch(status){ case SLEEP :System.out.println("正在睡觉");break; case WORKING:System.out.println("曾在工作");break; case EATING:System.out.println("正在吃饭");break; default:System.out.println("正在忙于其他事情"); } //输出结果是正在吃饭 }
注意:switch()只能用五种类型Char,byte,short,int,enum
1.3枚举的本质
定义枚举类型时本质上就是定义一个类别,只不过很多细节由编译器帮您完成了,所以在某些程度上,enum关键字的作用就像是class或interface。
当使用”enum”定义 枚举类型时,实质上定义出来的类型继承自java.lang.Enum类型,而每个枚举的成员其实就是您定义的枚举的一个实例,它们都是 public final static 类型的,所以你无法改变它们,可以直接使用。
JAVASE API 说明
Enum<E extends Enum<E>>是所有枚举类型的基类
说明了所有的enum类型的超类都是 java.lang.Enum
那么既然是一个类,那么就可以有成员以及构造方法。
下面新的PersonStatus枚举:
public enum PersonStatus { SLEEP("睡觉"),WORKING("工作"),EATING("吃饭"); String value; PersonStatus(String value){ this.value=value; } public String getValue(){ return this.value; } }
应用
public static void main(String[] args) { System.out.println(PersonStatus.SLEEP.getValue());//睡觉 }
可以看出比上面要简洁的多。
1.4枚举类型之间的比较
枚举类型的比较方法:compareTo(E o)
源码:
public final int compareTo(E o) { Enum other = (Enum)o; Enum self = this; if (self.getClass() != other.getClass() && // optimization self.getDeclaringClass() != other.getDeclaringClass()) throw new ClassCastException(); return self.ordinal - other.ordinal; }
可以看出枚举类型的比较主要在ordinal的变量的值
Ordinal值的解释:
/** * The ordinal of this enumeration constant (its position * in the enum declaration, where the initial constant is assigned * an ordinal of zero). * * Most programmers will have no use for this field. It is designed * for use by sophisticated enum-based data structures, such as * {@link java.util.EnumSet} and {@link java.util.EnumMap}. */ private final int ordinal;
意思是它是在枚举类型中声明的位置,第一个位置是0,以此类推。
一般用不到这个变量,只有在复杂的枚举结构类型中采用的到比较EnumSet,EnumMap(这两种类型在后面会讲到)。
Ordinal的demo:
public static void main(String[] args) { // 下面是for的增强循环方法,遍历枚举的所有值 for (ColorType color : ColorType.values()) { System.out.println(color + "的位置是 " + color.ordinal()); // RED的位置是 0 // BLACK的位置是 1 // YELLOW的位置是 2 } }
枚举比较的demo:
public static void main(String[] args) { compareToPersonStatus(PersonStatus.SLEEP); } public static void compareToPersonStatus(PersonStatus status){ for(PersonStatus stat : PersonStatus.values()){ System.out.println(status.compareTo(stat)); // 0 // -1 // -2 } }
二.枚举集合类型
2.1EnumSet
EnumSet的名称说明了其作用,它是J2SE 5.0后加入的新类别,可以协助建立枚举值的集合,它提供了一系列的静态方法,可以指定不同的集合的建立方式。
EnumSet的基本应用:
遍历枚举集合类型
public static void main(String[] args) { EnumSet<PersonStatus> set = EnumSet.of(PersonStatus.EATING, PersonStatus.SLEEP); // 遍历enumSet interratorPersonStatus(set); } public static void interratorPersonStatus(EnumSet<PersonStatus> set){ for (Iterator<PersonStatus> it = set.iterator(); it.hasNext();) { PersonStatus tmp = it.next(); System.out.println(tmp.getValue()); // 吃饭 // 睡觉 } }
上述用到的of方法,源码如下:
/** Creates an enum set initially containing the specified elements. * Overloadings of this method exist to initialize an enum set with * one through five elements. A sixth overloading is provided that * uses the varargs feature. This overloading may be used to create * an enum set initially containing an arbitrary number of elements, but * is likely to run slower than the overloadings that do not use varargs. * @param e1 an element that this set is to contain initially * @param e2 another element that this set is to contain initially * @throws NullPointerException if any parameters are null * @return an enum set initially containing the specified elements */ public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2) { EnumSet<E> result = noneOf(e1.getDeclaringClass()); result.add(e1); result.add(e2); return result; }
意思是创建一个set集合,并利用 e1 e2初始化。
上述方法利用到的noneOf源码:
/** * Creates an empty enum set with the specified element type. * @throws NullPointerException if <tt>elementType</tt> is null */ public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) { Enum[] universe = getUniverse(elementType); if (universe == null) throw new ClassCastException(elementType + " not an enum"); if (universe.length <= 64) return new RegularEnumSet<>(elementType, universe); else return new JumboEnumSet<>(elementType, universe); }
意思是创建一个指定类型的EnumSet集合,参数是class类型
noneOf Demo:
public static void noneOfPersonStatus(){ EnumSet<PersonStatus> set=EnumSet.noneOf(PersonStatus.class); set.add(PersonStatus.WORKING); set.add(PersonStatus.SLEEP); set.add(PersonStatus.EATING); interratorPersonStatus(set); //吃饭 // 工作 // 睡觉 }
利用noneOf的方法构造了Enumset,然后调用add方法添加枚举类型。
2.2 EnumMap
EnumMap的定义:EnumMap<K extends Enum<K>,V>
可以看出枚举映射中所有的键都必须来自单个枚举类型,该枚举类型在创建映射时显示或隐式的指定,枚举映射在内部表示为数组。
构造方法:
- EnumMap(Class <K> keyType)
- EnumMap(EnumMap<K,? extends V> m)
- EnumMap(Map<K,? extends V> m)
简单的应用demo:
public static void main(String[] args) { EnumMap<ColorType,String> map=new EnumMap<ColorType,String>(ColorType.class); map.put(ColorType.BLACK, "黑色"); map.put(ColorType.RED,"红色"); System.out.println(map.get(ColorType.RED));//红色 }