枚举类要注意的问题

public enum PayMode{

    POS(1, "POS支付"),
    ONLINE_PAY(2, "网银支付"),
    BALANCE_PAY(3, "资金余额支付"),
    OTHER(4, "其他支付");

    private int code;

    private String value;

    private static Map payModeType = new ConcurrentHashMap();

    static {
        for (PayMode payMode : PayMode.values()) {
            payModeType.put(payMode.getCode(), payMode);
        }
    }

    PayMode(int code, String value) {
        this.code = code;
        this.value = value;
    }

    public static PayMode getPayMode(int payModeCode) {
        return payModeType.get(payModeCode);
    }


}

看到上面代码的时候我首先考虑的是静态方法getPayMode能否根据code拿到枚举类实例?

众所周知,一个类的加载顺序是先加载静态块,静态方法,后加载构造器,但是在debug中会发现,枚举类的构造器是优先于静态部分先执行的,这是为什么呢?

解释如下:

所有的枚举值都是 public static final 的,为什么这么说,看下面代码

public enum Day {
    MONDAY("星期一"),
    TUESDAY("星期二"),
    WEDNESDAY("星期三"),
    THURSDAY("星期四"),
    FRIDAY("星期五"),
    SATURDAY("星期六"),
    SUNDAY("星期天");

    /**
     * 中文描述
     */
    private String desc;

    public String getDesc() {
        return desc;
    }

    /**
     * 私有构造方法,防止被外部调用
     * @param desc
     */
    private Day(String desc) {
        this.desc = desc;
    }

}

再看下反编译的结果

Compiled from "Day.java"
public final class Day extends java.lang.Enum {
  public static final Day MONDAY;
  public static final Day TUESDAY;
  public static final Day WEDNESDAY;
  public static final Day THURSDAY;
  public static final Day FRIDAY;
  public static final Day SATURDAY;
  public static final Day SUNDAY;
  private java.lang.String desc;
  private static final Day[] $VALUES;
  public static Day[] values();
  public static Day valueOf(java.lang.String);
  public java.lang.String getDesc();
  private Day(java.lang.String);
  static {};
}

 

是不是明白了,其实枚举类的实例都是public static final,只是隐式表达而已,那就解决了上面的第一个问题,为什么getPayMode能拿到枚举类实例。

那我们会想到另外一个问题,静态成员的加载顺序是按代码顺序加载的,如果把getPayMode  方法,或者private static Map payModeType = new ConcurrentHashMap()放最上面是不是就加载不了?

good question , 你这样做了之后你会发现,编译你都编译不过去,编译器都给你报错了。

答案是 --- 枚举类的所有实例(枚举值)必须在枚举类的第一行显式地列出,否则这个枚举类将永远不能产生实例,这是强制的。

所以你只要用枚举类,实例其实已经为你加载好了,你只要拿来用就ok了!

 

关于枚举类的解释,引用其他人写的,

枚举类构造器 只能使用 private 访问修饰符,所以无法从外部调用构造器,构造器只在构造枚举值时被调用;
使用 enum 定义的枚举类默认继承了 java.lang.Enum 类,并实现了 java.lang.Seriablizable 和 java.lang.Comparable 两个接口;
所有的枚举值都是 public static final 的,且非抽象的枚举类不能再派生子类;
枚举类的所有实例(枚举值)必须在枚举类的第一行显式地列出,否则这个枚举类将永远不能产生实例。列出这些实例(枚举值)时,系统会自动添加 public static final 修饰,无需程序员显式添加。

 

ref:

https://www.cnblogs.com/theRhyme/p/10192330.html

https://blog.csdn.net/weixin_34303897/article/details/87163915 

 

 

 

 

 

 

 

 

你可能感兴趣的:(Java)