1

这是一个快速的代码片段。对于类加载和初始化过程,我可以参考 JLS 第 12.4 和 12.5 节。仅当您访问非常量类的静态变量或可能访问静态方法时,才会加载该类。在我的情况下,我将变量声明为 final,删除 final 属性,检查类将被加载,静态初始化程序将运行。下面是修改后的代码

class staticFinalDemo1  {    
    //static final int var= 100;    
    static int var= 100;    

        static final void test()  {    
           System.out.println("Static Final Method Test");    
    }    
    static  {    
               System.out.println("Static Initializer");    
    }    
}    


class staticFinalDemo2 {    

        public static void main(String[] args)   {    

            System.out.println(staticFinalDemo1.var);    
            //staticFinalDemo1.test();    
        }    
    }    

现在我的观点是,如果我修改最终语句并将其替换为以下语句。

 static final Integer var= 100; 

静态初始化程序被加载。现在这个变量是一个常数。为什么在这种情况下加载静态初始化程序?是因为我使用了一个包装器对象,并且当我在类中引用它以供使用时,它的实例将被初始化?请澄清这个概念。

4

3 回答 3

4

不,这个变量不是编译时常量。常量只能是原始类型或字符串类型。整数不符合条件。

JLS §15.28

编译时常量表达式是表示原始类型值或字符串的表达式,它不会突然完成并且仅使用以下内容组成:[...]

于 2013-07-17T18:10:28.517 回答
2

非常量字段在构造函数中初始化。静态构造函数中的静态字段和实例构造函数中的实例字段。对于您的情况,请尝试制作 Integer 类型的变量并查看字节码:

class staticFinalDemo1 {
  static java.lang.Integer var;

  static {};
    Code:
       0: bipush        100
       2: invokestatic  #5                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
       5: putstatic     #6                  // Field var:Ljava/lang/Integer;
       8: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      11: ldc           #7                  // String Static Initializer
      13: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      16: return
}

在第 0 - 5 行,分配了 var 字段的值。bipush 将 100 加载到堆栈,invokestatic 创建 Integer 对象, putstatic 将其保存到静态变量。在 int 类型的情况下,这些行不存在。值已存在于常量池中。

于 2013-07-17T18:30:18.417 回答
1

大“I”整数不是常量,它是 Integer 对象的引用类型。在 java 中,您可以交替使用 Integer 和 int,但实际值不同。

于 2013-07-17T18:14:09.147 回答