枚举类的理解
枚举类型在级别上是与我们常用的class类型处于同一级别的。而作为区别,它有一些class类型不具备的特性,这也造就了枚举类独特的应用场景。
当我们所要定义的一个类的实例化对象只有有限个、确定的时,如:
- 月份:Jan(一月)、Feb(二月)、…、Dec(十二月)
- 季节:Spring(春季)、…、Winter(冬季)
- 支付方式:Cash(现金)、BankCard(银行卡)、Alipay(支付宝)、WeChatPay(微信支付)
- 订单状态:Nonpayment(未付款)、Paid(已付款)、Delivered(已发货)、Checked(已签收)
诸如上面所列举的情况,譬如当我们需要定义一个“月份”类来表示月份时,这个类的实例化对象实质上最多只需要有12个,分别表示12个月。因此这个类的实例化对象就是有限的(12个)、确定的(每个实例化对象都有其确定的含义)。
回顾上面所列举的例子,这种定义方式类似于定义常量。
实际上当我们把“月份”这个类的实例化对象创建好后,对于每个实例化对象,已经在其定义时对其做了相应的初始化。因此在后续代码中我们没有必要去修改他们的属性,这些实例化对象可以看成一种“常量”。
因此,总的来说,对于有以下需求的特殊的类型定义,我们可以使用enum枚举类进行类的定义。
- 类的对象只有有限个,且是确定的
- 需要定义的是一组常量
枚举类的使用
其实不通过使用enum也是可以直接通过class进行手动定义具有上述特性的枚举类的,只不过这种实现方式过于繁杂,因此在Java 5引入了enum进行枚举类的定义,下文将着重讲述enum的使用。
最简单的定义方式
我们先看一个最简单的例子。
enum Season {
SPRING,
SUMMER,
AUTUMN,
WINTER;
}
将我们需要的实例化对象名直接声明不需加任何修饰,中间以逗号分隔,这就已经是一个正确定义的、最简单的枚举类。我们可以通过类名+.的方式获取其实例化对象的引用。
Season autumn = Season.AUTUMN;
打印一下:
System.out.println(autumn); // AUTUMN
可以看到,在没有重写toString方法的前提下打印的并不是地址值,而是这个实例化对象的“名称”。这是因为enum定义的枚举类并不继承Object类,而是继承于Enum类。
System.out.println(Season.class.getSuperclass()); // class java.lang.Enum
添加属性和方法
有时候这么一个简单的枚举类定义并不能满足我们的要求,我们在先前基础上对其进行完善。
新增两个属性:
private final String name;
private final String color;
新增构造器和getter方法,需要注意构造器必须由private修饰而不能是public:
public String getName() {
return name;
}
public String getcolor() {
return color;
}
private Season (String name, String color) {
this.name = name;
this.color = color;
}
属性和方法的定义其实与一般的class相似,注意的是所有属性和方法的定义必须在实例化对象声明之后,换句话说,定义enum类后应该最先声明实例化的对象有哪些,然后再在下文定义属性和方法。
放回去修改我们的对象声明:
SPRING("春天","green"),
SUMMER("夏天","Red"),
AUTUMN("秋天","orange"),
WINTER("冬天","white");
实际上这里就已经调用了构造器。
至此,一个较为完整的枚举类就已经被成功定义,有需要的话可以再重写一下toString方法。
Enum类的常用方法
这里主要只介绍三个较常用的方法。
values():
返回枚举类型的对象数组。
Season[] seasons = Season.values();
for (int i = 0; i < seasons.length; i++) {
System.out.println(seasons[i]);
}
结果为:
SPRING
SUMMER
AUTUMN
WINTER
valuesOf(String str):
查找与传入字符串同名的枚举类对象,返回其引用。
Season autumn = Season.valueOf("AUTUMN");
System.out.println(autumn); // AUTUMN
若该枚举类对象不存在,将抛出IllegalArgumentException异常。
Season autumn = Season.valueOf("AUTUMN1");
System.out.println(autumn);
Exception in thread "main" java.lang.IllegalArgumentException: No enum constant Season.AUTUMN1
toString():
这个就不多介绍了,有需要直接重写即可。
实现接口
对于接口的一般实现,enum定义的枚举类与一般的class定义的类并无区别,这里主要讲的是enum定义的枚举类一种特殊的实现接口方法。
定义接口如下。
interface Info {
void show();
}
令枚举类实现该接口:
enum Season implements Info {
SPRING("春天","green"),
SUMMER("夏天","Red"),
AUTUMN("秋天","orange"),
WINTER("冬天","white");
...
正常情况下编译器会报错,因为我们没有实现Info接口中的show方法。
除了与class定义的类一样,在枚举类定义中直接实现show方法,我们还可以对每个枚举类对象单独进行show方法的实现。
效果如下:
enum Season implements Info {
SPRING("春天","green"){
@Override
public void show() {
}
},
SUMMER("夏天","Red") {
@Override
public void show() {
}
},
AUTUMN("秋天","orange") {
@Override
public void show() {
}
},
WINTER("冬天","white") {
@Override
public void show() {
}
};
这种实现接口的方式就是enum定义的枚举类所特有的。