java中枚舉實現原理


介紹

枚舉是java5新增的特性,我們可以用來替代以前用常量完成的功能。java對枚舉的支持還有EnumSet,EnumMap等工具類。

使用

public enum UserGenderEnum {
  MALE("0", "男"),
  FEMALE("1", "女"),
  NOT_KNOWN("2", "未知");

  private final String code;
  private final String info;

  UserGenderEnum(String code, String info) {
    this.code = code;
    this.info = info;
  }

  public String getCode() {
    return code;
  }

  public String getInfo() {
    return info;
  }
}
public class Client {
  public static void main(String[] args) {
    UserGenderEnum[] userGenderEnums = UserGenderEnum.values();
    for (UserGenderEnum genderEnum : userGenderEnums) {
      System.out.println("enum:" + genderEnum + "," + genderEnum.name() + "," + genderEnum.ordinal());
    }
    System.out.println(UserGenderEnum.valueOf("MALE"));
  }
}

輸出結果為

enum:MALE,MALE,0
enum:FEMALE,FEMALE,1
enum:NOT_KNOWN,NOT_KNOWN,2
MALE

我們看一下枚舉反編譯后的結果,如何反編譯看上一篇文章

public final class UserGenderEnum extends Enum<UserGenderEnum> {
    public static final /* enum */ UserGenderEnum MALE = new UserGenderEnum("MALE", 0, "0", "\u7537");
    public static final /* enum */ UserGenderEnum FEMALE = new UserGenderEnum("FEMALE", 1, "1", "\u5973");
    public static final /* enum */ UserGenderEnum NOT_KNOWN = new UserGenderEnum("NOT_KNOWN", 2, "2", "\u672a\u77e5");
    private final String code;
    private final String info;
    private static final /* synthetic */ UserGenderEnum[] $VALUES;

    public static UserGenderEnum[] values() {
        return (UserGenderEnum[])$VALUES.clone();
    }

    public static UserGenderEnum valueOf(String name) {
        return Enum.valueOf(UserGenderEnum.class, name);
    }

    private UserGenderEnum(String string, int n, String code, String info) {
        super(string, n);
        this.code = code;
        this.info = info;
    }

    public String getCode() {
        return this.code;
    }

    public String getInfo() {
        return this.info;
    }

    static {
        $VALUES = new UserGenderEnum[]{MALE, FEMALE, NOT_KNOWN};
    }
}

枚舉類默認繼承Enum抽象類,這也是枚舉不能繼承其他類的原因。編譯器幫我們創建了3個靜態實例,並將構造器設為私有,在我們的構造參數基礎上增加了name和ordinal兩個參數,indinal可以看做實例的索引。接下來我們看一下valueOf方法的實現原理,

這個方法是編譯器幫我們創建的,反編譯后才可以看到,

實際上調用的是Enum內部的方法,

繼續跟到Class類


終於看到了最終實現,可以看到Class還是調用了UserGenderEnum的values方法,上面可以看到values方法返回的是實例的數組,兜兜轉轉有回到了UserGenderEnum。
接下來看一下switch對枚舉的支持,

public class Client {
  public static void main(String[] args) {
    UserGenderEnum male = UserGenderEnum.MALE;
    switch (male) {
      case MALE:
        System.out.println("male");
        break;
      case FEMALE:
        System.out.println("female");
        break;
      case NOT_KNOWN:
        System.out.println("not_known");
        break;
    }
  }
}

反編譯結果為

public class Client {
    public static void main(String[] args) {
        UserGenderEnum male = UserGenderEnum.MALE;
        switch (male.ordinal()) {
            case 1: {
                System.out.println("male");
                break;
            }
            case 2: {
                System.out.println("female");
                break;
            }
            case 3: {
                System.out.println("not_known");
            }
        }
    }
}

可以看到最終還是轉成了int類型。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM