如何编写高质量代码--枚举篇

624 阅读6分钟

1 枚举简介

枚举类型是指由一组固定的常量组成合法值的类型

每当需要一组固定的常量,并且知道其成员的时候,应该使用枚举,例如:日期、加减乘除运算等

2 枚举的使用

JDk5之前定义一组int常量时,往往会这样做:

  public  static  final  int  APPLE_GRANNY_SMITH  =  2;
  public  static  final  int  ORANGE_NAVEL  =  0;
  public  static  final  int  ORANGE_TEMPLE  =  1;
  public  static  final  int  ORANGE_BLOOD  =  2;

初一看貌似没什么问题,但是int类型是作为一个常量体现的,其引用的值发生变动时,都需要重新编译。我们可以通过枚举来改造它

 public enum Fruit {
    
    APPLE_GRANNY_SMITH, ORANGE_NAVEL, ORANGE_TEMPLE, ORANGE_BLOOD;
    
}

System.out.println(Fruit.APPLE_GRANNY_SMITH)得到的结果为APPLE_GRANNY_SMITH,这时有人可能问,这打印的是个什么东西,其实我们声明的枚举,都是作为一个对象存在的,默认的toString()方法输出的都是本身。我们来继续改造它。

 public enum Fruit {
    
    APPLE_GRANNY_SMITHORANGE_NAVELORANGE_TEMPLEORANGE_BLOOD;
     @Override
    public String toString() {
        return String.valueOf(1+ordinal());
    }
}

System.out.println(Fruit.APPLE_GRANNY_SMITH)得到的结果为1,这时我们重写toString方法,ordinal()表示枚举的序数,默认从0开始,适用于EnumSet和EnumMap枚举类型。这里只是举例,平时请用实例变量来替代序数。我们继续改造。

 public enum Fruit {
    
    APPLE_GRANNY_SMITH(1), ORANGE_NAVEL(2), ORANGE_TEMPLE(2), ORANGE_BLOOD(1);
    //常量接收数据
    private final int num;
    //一个参数构造
    Day(int num) {
        this.num = num;
    }

    //获取值
    public int getNum() {
        return this.num;
    }
}

我们加入常量、有参构造、获取该值的getNum()方法,System.out.println(Fruit.APPLE_GRANNY_SMITH.getNum())得到的结果1,现在我们完全替代常量组的那种写法。我们可以继续优化,通过面向接口方式增加其可拓展性。

public enum Furit implements FuritNum{

    APPLE_GRANNY_SMITH(1){
        @Override
        public int getNum() {
            return 10;
        }
    }, ORANGE_NAVEL(2), ORANGE_TEMPLE(2), ORANGE_BLOOD(1);

    private final int num;

    Furit(int num) {
        this.num = num;
    }

    @Override
    public int getNum() {
        return this.num;
    }
}
//FuritNum接口
public interface FuritNum {

    public int getNum();

}

可以清晰看出,Furit枚举类实现了FuritNum接口,并且实现了getNum方法,System.out.println(Furit.APPLE_GRANNY_SMITH.getNum())得到的结果为10,APPLE_GRANNY_SMITH枚举对象重写了getNum方法,所以得到10。

我们可以通过枚举来简化if...else语句。

public void toPay(String code) {  
         if ("ZHIFUBAO".equals(code)) {  
             zhifubao.pay();  
         } elseif ("WEIXIN".equals(code)) {  
              weixin.pay();  
         } elseif ("JINGDONG".equals(code)) {  
              jingdong.pay();  
         } else {  
              System.out.println("请选择平台提供的支付方式支付");  
         }  
     }  

随着平台的业务扩展,支付方式的增多,上边的if...else语句也会越来越多。是否可以通过枚举的方式来简化if...else?

public enum PayEnum {

    WEIXIN("WEIXIN"new Weixin()),
    ZHIFUBAO("ZHIFUBAO"new ZhiFuBao());

    private final PayIy payIy;

    private final String code;

    PayEnum(String code, PayIy payIy) {
        this.code = code;
        this.payIy = payIy;
    }

    //枚举支付方法
    static void topay(String code) {
        //获取所有枚举
        PayEnum[] values = PayEnum.values();
        for (PayEnum value : values) {
            //根据每一个枚举对象获取K,判断K是否与code相等,相等获取V调用其方法
            if (value.getCode().equals(code)) {
                PayIy object =value.getPayIy();
                object.topay();
            }
        }
    }

    public PayIy getPayIy() {
        return payIy;
    }

    public String getCode() {
        return code;
    }
}
//支付接口
interface PayIy {
    void topay();
}

//微信支付
class Weixin implements PayIy {

    @Override
    public void topay() {
        System.out.println("微信支付");
    }
}

//支付宝支付
class ZhiFuBao implements PayIy {
    @Override
    public void topay() {
        System.out.println("支付宝支付");
    }
}

测试一下:

public class TestPay {

    public static void main(String[] args) {
        String code = "WEIXIN";
        topay(code);
    }

    //通过枚举简化
    public static void topay(String code) {
        //判断空值
        boolean noneEmpty = StringUtils.isEmpty(code);
        if (!noneEmpty) {
            //枚举调用支付业务
            PayEnum.topay(code);
        } else {
            System.out.println("参数不能为空");
        }
    }
}

该方法的时间复杂度为O(n),输出的结果为微信支付,当然这种方式只是一种实现方式,是否能实用到项目还是有待商榷。

以上就是枚举的全部内容,欢迎小伙伴们点赞留言。