目录
Java枚举Enum
枚举(enum)
enum全称enumeration,JDK 1.5中引入的新特性。在Java中,被enum关键字修饰的类型就是枚举类型,可以将枚举看成一个类,它继承于java.lang.enum类,当定义一个枚举类型时,每一个枚举类型成员都可以看作是枚举类型的一个实例,枚举类型成员默认被public static final修饰(所有的枚举值都是类静态常量),所以当使用枚举类型成员时直接使用枚举类型名称调用枚举类型成员即可。
enum Color {
RED, GREEN, BLUE;
}
如果枚举不添加任何方法,枚举值默认为从0开始的有序数值。以Color枚举类型举例,它的枚举常量依次为RED:0,GREEN:1,BLUE:2。
枚举的好处:可以将常量组织起来,统一进行管理
枚举的典型应用场景:错误码、状态机等
特性:除了不能继承,基本上可以将enum看做一个常规的类
枚举作用?
枚举是一种规范,它规范了参数的形式,这样就可以不用考虑类型的不匹配并且显式的替代了int型参数可能带来的模糊概念。枚举像一个类,又像一个数组。
优势
(1)类型安全
(2)紧凑有效的数据定义
(3)可以和程序其他部分完美交互
(4)运行效率高
本质
尽管enum看起来像是一种新的数据类型,事实上,enum是一种受限制的类,并且具有自己的方法。创建enum时,编译器会生成一个相关的类,这个类继承自java.lang.Enum
构造方法
在枚举类型中,可以添加构造方法,但是规定这个构造方法必须为private修饰符或者默认修饰符所修饰
public enum Color {
RED(1, "红色"), GREEN(2, "绿色"), RED_ONE(1);
private int index;
private String value;
private Color() {
// 无参构造
}
private Color(int index) {
this.index = index;
}
private Color(int index, String value) {
// 有参构造
this.index = index;
this.value = value;
}
}
保存枚举值,应该是要保存int值,如果保存字符串,在使用中英文切换可能就会出问题
枚举类型可以实现一个或多个接口,但是不能继承类。因为编译器会默认将枚举类型继承自java.lang.Enum类,这一过程由编译器完成;枚举类型中的常量成员必须在其他成员之前定义,否则这个枚举类型不会产生对象
方法
方法 | 描述 |
---|---|
values() | 返回enum实例的数组。数组中的元素严格保持在enum中声明时的顺序 |
name() | 返回实例名 |
ordinal() | 返回实例声明时的次序,从0开始 |
getDeclaringClass() | 返回实例所属的enum类型 |
equals() | 判断是否为同一个对象 |
可以使用==来比较enum实例。此外,java.lang.Enum实现了Comparable和 Serializable 接口,所以也提供 compareTo()方法
为枚举显示的赋值。Java不允许使用“=”为枚举常量赋值;enum可以添加普通方法、静态方法、抽象方法、构造方法为枚举赋值。
Java虽然不能直接为实例赋值,但是它有更优秀的解决方案:为enum添加方法来间接实现显示赋值。创建enum时,可以为其添加多种方法,甚至可以为其添加构造方法
注意:如果要为enum定义方法,那么必须在enum的最后一个实例尾部添加一个分号。此外,在enum中,必须先定义实例,不能将字段或方法定义在实例前面。否则,编译器会报错。
常见用法
1.常量
枚举可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法
public enum Color {
RED, GREEN, BLANK, YELLOW;
}
2.Switch
JDK1.6之前的switch语句只支持int,char,enum类型,使用枚举,能让代码可读性更强
enum Color {
GREEN, YELLOW, RED;
}
class TrafficLight {
Color color = Color.RED;
public void change() {
switch (color) {
case RED:
color = Color.GREEN;
break;
case YELLOW:
color = Color.RED;
break;
case GREEN:
color = Color.YELLOW;
break;
}
}
}
3.向枚举中添加新方法
public enum Color {
RED(1, "红色"), GREEN(2, "绿色"), BLANK(3, "白色"), YELLO(4, "黄色");
// 成员变量
private int index;
private String name;
private Color(int index, String name) {// 构造方法
this.name = name;
this.index = index;
}
// 普通方法
public static String getName(int index) { //定义了才能使用RED(1, "红色")
for (Color c : Color.values()) {
if (c.getIndex() == index) {
return c.name;
}
}
return null;
}
// getter、setter
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
}
4.覆盖枚举的方法
toString()方法覆盖
public enum Color {
RED(1, "红色"), GREEN(2, "绿色"), BLANK(3, "白色"), YELLO(4, "黄色");
// 成员变量
private int index;
private String name;
private Color(int index, String name) {// 构造方法
this.name = name;
this.index = index;
}
@Override
public String toString() {// 覆盖toString方法
return this.index + "_" + this.name;
}
}
5.实现接口
所有的枚举都继承自java.lang.Enum类。由于Java不支持多继承,所以枚举对象不能再继承其他类,但是可以实现接口(implements)。
interface Behaviour {
void print();
String getInfo();
}
public enum Color implements Behaviour {
RED(1, "红色"), GREEN(2, "绿色"), BLANK(3, "白色"), YELLO(4, "黄色");
// 成员变量
private int index;
private String name;
// 构造方法
private Color(int index, String name) {
this.name = name;
this.index = index;
}
//接口方法
@Override
public String getInfo() {
return this.name;
}
@Override
public void print() {
System.out.println(this.index + ":" + this.name);
}
}
6.使用接口组织枚举
public interface Food {
enum Coffee implements Food {
BLACK_COFFEE,DECAF_COFFEE,LATTE,CAPPUCCINO;
}
enum Dessert implements Food{
FRUIT, CAKE, GELATO;
}
}
7.枚举集合
java.util.EnumSet 和 java.util.EnumMap 是两个枚举集合
EnumSet保证集合中的元素不重复;EnumMap中的 key是enum类型,而value则可以是任意类型
EnumSet
EnumSet是一个抽象类,它继承自AbstractSet并实现了Set接口。它专门用于存储枚举类型的元素集合,且集合中的元素必须属于同一个枚举类型。
EnumSet内部使用位向量的形式来表示集合元素的存在与否,因此在性能上具有很高的效率。它提供了一些静态工厂方法用于创建不同类型的EnumSet。
例如:allOf、noneOf、of等。EnumSet是一个轻量级的集合类,通常用于代替传统的基于位运算的枚举集合实现。
enum Color {
RED, GREEN, BLUE
}
EnumSet<Color> colors = EnumSet.of(Color.RED, Color.BLUE);
System.out.println(colors); // 输出 [RED, BLUE]
EnumMap
EnumMap是一个实现了Map接口的具体类,用于存储枚举类型作为键的键值对。它的键必须属于同一个枚举类型,而值可以是任意对象。EnumMap内部使用数组来表示键值对,数组的索引与枚举常量的顺序对应。因此,EnumMap的性能非常高效,并且具有很小的内存开销。EnumMap提供了与Map接口一致的方法,同时也定义了一些特有的方法,如keySet、values和entrySet等。
如何使用EnumMap:
enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
EnumMap<Day, String> schedule = new EnumMap<>(Day.class);
schedule.put(Day.MONDAY, "Work");
schedule.put(Day.FRIDAY, "Party");
System.out.println(schedule.get(Day.MONDAY)); // 输出 "Work"
System.out.println(schedule.get(Day.TUESDAY)); // 输出 null
枚举遍历
for (RnumTest e : RnumTest.values()) {
System.out.println(e.toString());
}