这是一段快速代码。对于类加载和初始化过程,我可以与JLS第12.4和12.5节相关。只有在访问类不是常量的静态变量或者可以访问静态方法时才会加载该类。在我的情况下,我将变量声明为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;
静态初始化程序被加载。现在这个变量是一个常数。为什么要加载 在这种情况下静态初始化程序?是因为我正在使用包装器对象及其实例 当我在课堂上推荐它时,它会被初始化吗?请澄清这个概念。
本
答案 0 :(得分:4)
不,这个变量不是编译时常量。常量只能是基本类型或String类型。整数不符合条件。
请参阅JLS §15.28:
编译时常量表达式是表示基本类型值的表达式或不突然完成的字符串,仅使用以下内容组成:[...]
答案 1 :(得分: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类型的情况下,这些行不存在。值已经存在于常量池中。
答案 2 :(得分:1)
Big'I'整数不是常量,它是Integer对象的引用类型。在java中,您可以互换使用Integer和int,但实际值不同。