美文网首页技术干货
枚举——静态常量

枚举——静态常量

作者: zoyanhui | 来源:发表于2017-04-19 15:23 被阅读0次

    在java中枚举有个特点,枚举实例的定义要求在枚举类型的第一行, 而且,枚举构造器的调用,会在static块的调用之前。
    这里给出例子:

    源java文件 EnumDemo.java:

    import java.util.ArrayList;
    import java.util.List;
    
    public enum EnumDemo {
        ONE(1), TWO(2);
    
        private final static List<Integer> vals;
        static {
            System.out.println("fetch instance from static");
            vals = new ArrayList<>();
            EnumDemo[] values = EnumDemo.values();
            for (EnumDemo value : values) {
                vals.add(value.val);
            }
        }
    
        private int val;
        EnumDemo(int val){
            this.val = val;
            System.out.println("create instance:" + val);
        }
    }
    

    如果使用EnumDemo这个枚举,会得到如下输出:

    create instance:1
    create instance:2
    fetch instance from static
    

    可以看到构造器调用发生在static块之前,这是什么原因呢?

    下面观察一下上面代码对应的bytecode。使用javac把源java文件编译成class文件, 然后对class文件使用javap, javap -c EnumDemo.class, 得到:

    Compiled from "EnumDemo.java"
    public final class EnumDemo extends java.lang.Enum<EnumDemo> {
      public static final EnumDemo ONE;
    
      public static final EnumDemo TWO;
    
      public static EnumDemo[] values();
        Code:
           0: getstatic     #1                  // Field $VALUES:[LEnumDemo;
           3: invokevirtual #2                  // Method "[LEnumDemo;".clone:()Ljava/lang/Object;
           6: checkcast     #3                  // class "[LEnumDemo;"
           9: areturn       
    
      public static EnumDemo valueOf(java.lang.String);
        Code:
           0: ldc_w         #4                  // class EnumDemo
           3: aload_0       
           4: invokestatic  #5                  // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
           7: checkcast     #4                  // class EnumDemo
          10: areturn       
    
      static {};
        Code:
           0: new           #4                  // class EnumDemo
           3: dup           
           4: ldc           #16                 // String ONE
           6: iconst_0      
           7: iconst_1      
           8: invokespecial #17                 // Method "<init>":(Ljava/lang/String;II)V
          11: putstatic     #18                 // Field ONE:LEnumDemo;
          14: new           #4                  // class EnumDemo
          17: dup           
          18: ldc           #19                 // String TWO
          20: iconst_1      
          21: iconst_2      
          22: invokespecial #17                 // Method "<init>":(Ljava/lang/String;II)V
          25: putstatic     #20                 // Field TWO:LEnumDemo;
          28: iconst_2      
          29: anewarray     #4                  // class EnumDemo
          32: dup           
          33: iconst_0      
          34: getstatic     #18                 // Field ONE:LEnumDemo;
          37: aastore       
          38: dup           
          39: iconst_1      
          40: getstatic     #20                 // Field TWO:LEnumDemo;
          43: aastore       
          44: putstatic     #1                  // Field $VALUES:[LEnumDemo;
          47: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
          50: ldc           #21                 // String fetch instance from static
          52: invokevirtual #15                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
          55: new           #22                 // class java/util/ArrayList
          58: dup           
          59: invokespecial #23                 // Method java/util/ArrayList."<init>":()V
          62: putstatic     #24                 // Field vals:Ljava/util/List;
          65: invokestatic  #25                 // Method values:()[LEnumDemo;
          68: astore_0      
          69: aload_0       
          70: astore_1      
          71: aload_1       
          72: arraylength   
          73: istore_2      
          74: iconst_0      
          75: istore_3      
          76: iload_3       
          77: iload_2       
          78: if_icmpge     109
          81: aload_1       
          82: iload_3       
          83: aaload        
          84: astore        4
          86: getstatic     #24                 // Field vals:Ljava/util/List;
          89: aload         4
          91: getfield      #7                  // Field val:I
          94: invokestatic  #26                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
          97: invokeinterface #27,  2           // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
         102: pop           
         103: iinc          3, 1
         106: goto          76
         109: return        
    }
    

    可见,枚举实例也是static的,而且必须在第一行定义,就满足了,是整个枚举类的头部static块。所以会先执行。

    相关文章

      网友评论

        本文标题:枚举——静态常量

        本文链接:https://www.haomeiwen.com/subject/tqchzttx.html