一、枚举类型
/**
* @author zhangys
* @description
* @date 2020/4/15
*/
public class EnumTest {
enum Day {
SUNDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}
public static void main(String[] args) {
System.out.println(Day.SUNDAY);
System.out.println(TestEnum.VALUE1);
}
}
enum TestEnum {
VALUE1, VALUE2
}
//输出
SUNDAY
VALUE1
二、switch 操作
enum 支持 switch 操作。
/**
* @author zhangys
* @description
* @date 2020/4/15
*/
public class EnumTest {
enum Day {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}
public static void main(String[] args) {
Day today = Day.WEDNESDAY;
switch (today) {
case MONDAY:
System.out.println(Day.MONDAY);
break;
case TUESDAY:
System.out.println(Day.TUESDAY);
break;
case WEDNESDAY:
System.out.println(Day.WEDNESDAY);
break;
case THURSDAY:
System.out.println(Day.THURSDAY);
break;
case FRIDAY:
System.out.println(Day.FRIDAY);
break;
case SATURDAY:
System.out.println(Day.SATURDAY);
break;
case SUNDAY:
System.out.println(Day.SUNDAY);
break;
}
}
}
//enum TestEnum {
// VALUE1, VALUE2
//}
三、自定义枚举类
可以通过定制 Enum 类型来定义自己的枚举类。需要注意的是枚举类型的构造函数是私有的 private,所以不能通过 New 来创建枚举类型,正因如此才保证了枚举数据类型的安全,不会被更改。如:定义一个 Day enum 类型:
/**
* @author zhangys
* @date 2020/4/15
*/
public enum Day {
SUNDAY(7, "周日"), MONDAY(1, "周一"), TUESDAY(2, "周二"),
WEDNESDAY(3, "周三"), THURSDAY(4, "周四"), FRIDAY(5, "周五"),
SATURDAY(6, "周六");
private Integer code;
private String name;
Day(Integer code, String name) {
this.code = code;
this.name = name;
}
;
public Integer getCode() {
return code;
}
public String getName() {
return name;
}
}
测试
/**
* @author zhangys
* @description
* @date 2020/4/15
*/
public class EnumTest {
public static void main(String[] args) {
Day today = Day.WEDNESDAY;
switch (today) {
case MONDAY:
System.out.println(Day.MONDAY.getName());
break;
case TUESDAY:
System.out.println(Day.TUESDAY.getName());
break;
case WEDNESDAY:
System.out.println(Day.WEDNESDAY.getName());
break;
case THURSDAY:
System.out.println(Day.THURSDAY.getName());
break;
case FRIDAY:
System.out.println(Day.FRIDAY.getName());
break;
case SATURDAY:
System.out.println(Day.SATURDAY.getName());
break;
case SUNDAY:
System.out.println(Day.SUNDAY.getName());
break;
}
}
}
//结果
周三
四、相关枚举类
4.1 EnumMap 枚举型映射/字典
EnumMap 是对 Map 接口的实现类,其 key-value 映射中的 key 是 Enum 类型,其原理是一个对象数组,数组的下标索引就是根据 Map 中的 key 直接获取(即枚举中的 ordinal 值),数组长度就是枚举类成员个数;当 key 为枚举类型时其效率比 HashMap 高,因为可以直接获取数组下标索引访问到元素;此外 EnumMap 是保证顺序的,输出是按照 key 在枚举中的顺序来确定的。
EnumMap 的构造方法
//需要传递一个类型信息,因为没有这个类信息就不知道具体的枚举类是什么,
// 也就无法初始化内部的数据结构。
public EnumMap(Class < K > keyType)
// 其他构造方法。
public EnumMap(EnumMap < K, ? extends V > m )
public EnumMap(Map < K, ? extends V > m )
EnumMap 的实现原理
EnumMap 的实现原理依赖内部两个长度相同的数组,一个表示所有可能的键,一个表示对应的值,当放入 key-value 时首先会检查键的类型,如果类型不对会抛出异常,否则调用 key 的 ordinal 获取索引 index,并将值 value 放入值数组 vals[index] 中(注意:如果值 value 为 null,则为了区别真正的 null 与没有值,EnumMap 会将 null 值包装成一个特殊的对象)。
其构造方法主要就是在初始化相关数组,如下:
public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements java.io.Serializable, Cloneable {
//key键的具体枚举类型
private final Class<K> keyType;
// key的所有枚举值
private transient K[] keyUniverse;
// EnumMap的存储实现,仅仅为一个枚举成员个数长度的数组
private transient Object[] vals;
......
// 构造方法
public EnumMap(Class<K> keyType) {
// key的枚举类型赋值
this.keyType = keyType;
// 获取枚举类的所有枚举值存入数组缓存使用
keyUniverse = getKeyUniverse(keyType);
// 实例化枚举值个数长度的数组
vals = new Object[keyUniverse.length];
}
......
}
测试
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
/**
* @author zhangys
* @description
* @date 2020/4/15
*/
public class EnumMapTest {
public static void main(String[] args) {
EnumMap<Day,String> enumMap = new EnumMap<Day, String>(Day.class);
enumMap.put(Day.WEDNESDAY,"今天是周三");
Map<Day,String> map = new HashMap<>();
map.put(Day.WEDNESDAY,"今天是周三");
System.out.println("enumMap:"+enumMap.get(Day.WEDNESDAY));
System.out.println("map:"+map.get(Day.WEDNESDAY));
}
}
4.2 EnumSet 枚举集合
EnumSet 是个抽象类,不能实例化,查看源码发现有提供静态实例化 JumboEnumSet 或 RegularEnumSet 对象的方法。这两个对象继承自 EnumSet,区别在于 EnumSet 大小,大于 64 时创建的是 JumboEnumSet 对象,小于 64 时创建的是 RegularEnumSet 对象。
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
/**
* @author zhangys
* @description
* @date 2020/4/15
*/
public class EnumMapTest {
public static void main(String[] args) {
EnumSet<Day> enumSet = EnumSet.noneOf(Day.class);
enumSet.add(Day.WEDNESDAY);
enumSet.add(Day.MONDAY);
System.out.println(enumSet.toString());
for (Day day:enumSet){
System.out.println("code:" + day.getCode()+"name:"+day.getName());
}
enumSet.clear();
System.out.println(enumSet);
}
}
//输出
[MONDAY, WEDNESDAY]
code:1name:周一
code:3name:周三
[]
EnumSet 是非线程安全的,要想线程安全使用 Collections.synchronizedSet() 处理 numSet 对象,如:
Set<Day> enumSet = Collections.synchronizedSet(EnumSet.noneOf(Day.class));