并提供了 values() 和 valueOf(String name) 的静态方法。
我们定义的枚举变量实际上是编译器帮我们自动生成了构造函数。
所有枚举类都是 Enum 的子类,枚举类可以实现一个或多个接口。
EnumEnum 是所有 Java 语言枚举类型的公共基类,实现了 Comparable 和 Serializable 接口。它包含 final 类型的 name 和 ordinal (此枚举常量的序号,从0开始)属性,下面我们来了解下它的方法
protected Enum(String name, int ordinal);——构造方法;
public String toString();——返回 name 字段,即枚举定义枚举变量的字符串;
protected final Object clone();——抛出 CloneNotSupportedException 异常,保证枚举类永远不会被克隆;
public final Class getDeclaringClass();——返回与此枚举常量的枚举类型对应的类对象;
protected final void finalize();—— 枚举类不能有 finalize 方法;
readObject(ObjectInputStream in);& readObjectNoData();—— 抛出InvalidObjectException 异常,防止默认反序列化;
扩展枚举类中可以自定义属性
自定义的属性值最好用 private final 修饰,防止生成的 set 方法在使用时修改属性值,使代码更加安全。
枚举类中可以自定义构造函数
构造函数必须为 private 修饰,防止在别处声明此类对象。
枚举类可以自定义方法,枚举项可以选择性覆盖自定义的方法。
public enum OrderStatus{NO_PAY("未支付",0),
PAY("已支付",1){
@Override
public void printOrderStatus() {
System.out.println("已支付");
}
},
REFUNDING("退款中",2),
REFUNDED("退款成功",3),
FAIL_REFUNDED("退款失败",4),
;
private final String name;
private final int status;
private OrderStatus(String name,int status){
this.name = name;
this.status = status;
}
public void printOrderStatus(){
System.out.println("打印订单状态");
}
}
public class EnumTest {
public static void main(String[] args) {
OrderStatus.PAY.printOrderStatus();
OrderStatus.NO_PAY.printOrderStatus();
}
}
枚举类也可以有抽象方法,但是枚举项必须重写该方法。
枚举类实现接口
与普通类一样,实现接口的时候需要实现接口的抽象方法,也可以让枚举类的不同对象实现不同的行为。
例
//定义一个接口public interface Order {
void printOrderStatus();
}
//枚举类实现该接口
public enum OrderStatus implements Order{
NO_PAY("未支付",0){
@Override
public void printOrderStatus() {
System.out.println("未支付");
}
},
PAY("已支付",1){
@Override
public void printOrderStatus() {
System.out.println("已支付");
}
},
REFUNDING("退款中",2){
@Override
public void printOrderStatus() {
System.out.println("退款中");
}
},
REFUNDED("退款成功",3){
@Override
public void printOrderStatus() {
System.out.println("退款成功");
}
},
FAIL_REFUNDED("退款失败",4){
@Override
public void printOrderStatus() {
System.out.println("退款失败");
}
},
;
private final String name;
private final int status;
private OrderStatus(String name,int status){
this.name = name;
this.status = status;
}
}
此时查看编译后的文件,会发现除了生成 OrderStatus.class 文件之外,还生成了多个 .class 文件:
它们是 OrderStatus.class 中生成的匿名内部类的文件。
状态转换 需求订单是电商项目中不可缺少的组成部分,而订单状态的转换也是我们经常讨论的问题。我们都知道订单状态的转换是有一定的逻辑性的,不可以随意转换。
例:你想购买某个商品,只是把它加入了购物车,此时应该是未支付状态。如果来个请求想把它转换为退款状态,那么系统应该抛出提示信息“状态转换失败,请先完成购买!”
接下来我们就用枚举来完成一下订单状态转换的限制。
实现枚举类定义:
public enum OrderStatus{NO_PAY("未支付",0){
@Override
public Boolean canChange(OrderStatus orderStatus) {
switch (orderStatus){
case PAY:
return true;
default:
return false;
}
}
},
PAY("已支付",1){
@Override
public Boolean canChange(OrderStatus orderStatus) {
//因为退款接口一般都会有延迟,所以会先转化为“退款中”状态
switch (orderStatus){
case REFUNDING:
return true;
default:
return false;
}
}
},
REFUNDING("退款中",2){
@Override
public Boolean canChange(OrderStatus orderStatus) {
switch (orderStatus){
case REFUNDED:
case FAIL_REFUNDED:
return true;
default:
return false;
}
}
},
REFUNDED("退款成功",3),
FAIL_REFUNDED("退款失败",4),
;
private final String name;
private final int status;
private OrderStatus(String name,int status){
this.name = name;
this.status = status;
}
//自定义转换方法
public Boolean canChange(OrderStatus orderStatus){
return false;
}
}
调用方法:
public class EnumTest {public static void main(String[] args) {
Boolean aBoolean = OrderStatus.NO_PAY.canChange(OrderStatus.PAY);
String statusStr = aBoolean?"可以":"不可以";
System.out.println("是否可以完成状态转换:"+ statusStr);
Boolean flag = OrderStatus.REFUNDED.canChange(OrderStatus.FAIL_REFUNDED);
String flagStr = flag?"可以":"不可以";
System.out.println("是否可以完成状态转换:"+ flagStr);
}
}
返回结果:
这样我们就用枚举类实现了订单状态转换的限制。此例子只是为状态转换提供一种思路,具体的流程还需要根据自己系统中的业务来具体处理。