【java基础】枚举

public enum Color {
    Red,Blue,Green;
}
Color red = Color.Red;//枚举的其中一个类型
Color[] values = Color.values();//获取所有的枚举类型
String name = red.name();//可以获得枚举值的名称
int ordinal = red.ordinal();//可以获得枚举值的编号

那我们定义枚举类型后,到底发生了什么呢?我们对枚举的实现原理进行探究。
我们来解析下Color.class文件,命令 javap Color

public final class Color extends java.lang.Enum<color> {
  public static final Color Red;
  public static final Color Blue;
  public static final Color Green;
  public static final Color[] $VALUES;
  public static Color[] values();
  public static Color valueOf(java.lang.String);
  static {};
}
</color>

从解析后的文件中我们可以知道

进一步细化Color.class
命令 javap -c Color

public final class Color extends java.lang.Enum<color> {
  public static final Color Red;
  public static final Color Blue;
  public static final Color Green;
  public static Color[] values();
    Code:
       0: getstatic     #1                  // Field $VALUES:[LColor;
       3: invokevirtual #2                  // Method "[LColor;".clone:()Ljava/lang/Object;
       6: checkcast     #3                  // class "[LColor;"
       9: areturn

  public static Color valueOf(java.lang.String);
    Code:
       0: ldc           #4                  // class Color
       2: aload_0
       3: invokestatic  #5                  // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljav
a/lang/Enum;
       6: checkcast     #4                  // class Color
       9: areturn

  static {};
    Code:
       0: new           #4                  // class Color
       3: dup
       4: ldc           #7                  // String Red
       6: iconst_0
       7: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
      10: putstatic     #9                  // Field Red:LColor;
      13: new           #4                  // class Color
      16: dup
      17: ldc           #10                 // String Blue
      19: iconst_1
      20: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
      23: putstatic     #11                 // Field Blue:LColor;
      26: new           #4                  // class Color
      29: dup
      30: ldc           #12                 // String Green
      32: iconst_2
      33: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
      36: putstatic     #13                 // Field Green:LColor;

      39: iconst_3
      40: anewarray     #4                  // class Color
      43: dup

      44: iconst_0
      45: getstatic     #9                  // Field Red:LColor;
      48: aastore
      49: dup
      50: iconst_1
      51: getstatic     #11                 // Field Blue:LColor;
      54: aastore
      55: dup
      56: iconst_2
      57: getstatic     #13                 // Field Green:LColor;
      60: aastore
      61: putstatic     #1                  // Field $VALUES:[LColor;
      64: return
}
</init></init></init></color>

还原后的代码如下:

public final class Color extends java.lang.Enum<color> {
    //&#x5B9A;&#x4E49;&#x7684;&#x679A;&#x4E3E;&#x6210;&#x5458;
    public static final Color Red;
    public static final Color Blue;
    public static final Color Green;
    //&#x7F16;&#x8BD1;&#x5668;&#x81EA;&#x52A8;&#x751F;&#x6210;&#x7684; javap -c &#x8FD8;&#x67E5;&#x4E0D;&#x51FA;&#x6765;&#xFF0C;&#x7591;&#x60D1;
    public static final /* synthetic */ Color[] $VALUES;//&#x7F16;&#x8BD1;&#x5668;&#x81EA;&#x52A8;&#x751F;&#x6210;&#x7684;
    public static Color[] values(){
        /**
         * 0: getstatic     #1                  // Field $VALUES:[LColor;
         * 3: invokevirtual #2                  // Method "[LColor;".clone:()Ljava/lang/Object;
         * 6: checkcast     #3                  // class "[LColor;"
         * 9: areturn
         */
        return $VALUES.clone();
    }
    public static Color valueOf(java.lang.String s){
        /**
         * 0: ldc           #4                  // class Color
         * 2: aload_0
         * 3: invokestatic  #5                  // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljav
         * a/lang/Enum;
         * 6: checkcast     #4                  // class Color
         * 9: areturn
         */
        return Enum.valueOf(Color.class,s);
    }
    protected Color(String name, int ordinal) {
        super(name, ordinal);
    }
    static {
        /**
         * 0: new           #4                  // class Color
         * 3: dup
         * 4: ldc           #7                  // String Red
         * 6: iconst_0
         * 7: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
         * 10: putstatic     #9                  // Field Red:LColor;
         */
        Red=new Color("Red",0);
        /**
         * 13: new           #4                  // class Color
         * 16: dup
         * 17: ldc           #10                 // String Blue
         * 19: iconst_1
         * 20: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
         * 23: putstatic     #11                 // Field Blue:LColor;
         */
        Blue=new Color("Blue",1);
        /**
         * 26: new           #4                  // class Color
         * 29: dup
         * 30: ldc           #12                 // String Green
         * 32: iconst_2
         * 33: invokespecial #8                  // Method "<init>":(Ljava/lang/String;I)V
         * 36: putstatic     #13                 // Field Green:LColor;
         */
        Green=new Color("Green",2);
        /**
         * 39: iconst_3
         * 40: anewarray     #4                  // class Color
         * 43: dup
         * 44: iconst_0
         * 45: getstatic     #9                  // Field Red:LColor;
         * 48: aastore
         * 49: dup
         * 50: iconst_1
         * 51: getstatic     #11                 // Field Blue:LColor;
         * 54: aastore
         * 55: dup
         * 56: iconst_2
         * 57: getstatic     #13                 // Field Green:LColor;
         * 60: aastore
         * 61: putstatic     #1                  // Field $VALUES:[LColor;
         */
        $VALUES=new Color[]{Red,Blue,Green};
    };
}
</init></init></init></color>

通过上面还原后的代码可知,在类的 static&#x4EE3;&#x7801;&#x5757;中编译器帮我们生成枚举中的每个成员,实际上就是生成对象并赋值给静态变量。

单例模式

枚举其实就是编译帮我们在静态代码块中创建一个或多个枚举成员对象,如果我们只定义一个枚举成员,这样就是一个单例对象

public enum Singleton {
    INSTANCE;
    public void doSometing(){
        System.out.println("doing");
    }
}

代码如此简单,不仅如此,这样的方式还可以解决 &#x53CD;&#x5C04;&#x653B;&#x51FB;&#x53CD;&#x5E8F;&#x5217;&#x5316;导致的单例失败的问题。

在获取实例时进行了枚举判断,如果是枚举类型的则直接抛出异常。

Jdk1.8 Class.clss 文件的 416..417

public T newInstance(Object ... initargs)
        throws InstantiationException, IllegalAccessException,
               IllegalArgumentException, InvocationTargetException{
        ....

        if ((clazz.getModifiers() & Modifier.ENUM) != 0)
            throw new IllegalArgumentException("Cannot reflectively create enum objects");
        .....

        return inst;
    }

枚举的序列时仅降枚举对象的name属性输出到结果中,在反序列化时则是通过 java.lang.EnumvalueOf方法来根据名字在jvm中查找对象的。

同时编译器还禁止对枚举的定制化序列机制,因此禁用了writeObject、readObject、readObjectNoData、writeReplace和readResolve等方法。

策略模式

一种行为,多种结果,不同结果的实现,名曰策略。

public enum Calculator {
    //&#x52A0;&#x6CD5;&#x8FD0;&#x7B97;
    ADD("+"){
        public int exec(int a,int b){
            return a+b;
        }
    },
    //&#x51CF;&#x6CD5;&#x8FD0;&#x7B97;
    SUB("-"){
        public int exec(int a,int b){
            return a - b;
        }
    };
    String value = "";
    //&#x5B9A;&#x4E49;&#x6210;&#x5458;&#x503C;&#x7C7B;&#x578B;
    Calculator(String _value){
        this.value = _value;
    }
    //&#x83B7;&#x5F97;&#x679A;&#x4E3E;&#x6210;&#x5458;&#x7684;&#x503C;
    public String getValue(){
        return this.value;
    }
    //&#x58F0;&#x660E;&#x4E00;&#x4E2A;&#x62BD;&#x8C61;&#x51FD;&#x6570;
    public abstract int exec(int a,int b);
}

Original: https://www.cnblogs.com/hitechr/p/15104914.html
Author: Hitechr
Title: 【java基础】枚举

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/590451/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球