我正在尝试运行此代码,但是我发现了最终的静态行为:代码运行时没有执行A的静态块。请提供原因。
class A {
final static int a=9;
static { //this block is not executing ??
System.out.println("static block of A");
}
}
class Manager {
static {
System.out.println("manager sib");
}
public static void main(String ...arg) {
System.out.println("main");
System.out.println(A.a);
}
}
为什么A类的静态块不运行?
答案 0 :(得分:7)
问题在于A.a
是constant variable。
基本类型或类型String的变量,是最终的并使用编译时常量表达式(第15.28节)初始化,称为常量变量。
因此,您的Manager.main
方法完全编译,就好像它是:
public static void main(String ...arg) {
System.out.println("main");
System.out.println(9);
}
A.a
不再有真正的引用,因此A
类甚至不需要存在,更不用说初始化了。 (您可以删除A.class
并仍然运行Manager
。)
如果您依赖于使用A.a
来确保初始化类型,则不应添加无操作方法:
public static void ensureClassIsInitialized() {
}
然后从main
方法中调用 。尽管如此,这是非常不寻常的。
答案 1 :(得分:1)
规范http://docs.oracle.com/javase/specs/jls/se7/jls7.pdf 第4.12.1节说,
一个原始类型或类型String的变量,它是final的并用a初始化 编译时常量表达式(第15.28节),称为常量变量。 变量是否是常量变量可能会产生影响 类初始化(第12.4.1节),二进制兼容性(第13.1节,第13.4.9节)和明确的 任务(§16)。
由于您只访问常量,因此不需要类初始化。
答案 2 :(得分:0)
你可以强制加载你需要的任何课程:
public final class ClassUtils {
private ClassUtils() {}
public static void forceLoad(Class<?>... classes) {
for (Class<?> clazz : classes) {
try {
Class.forName(clazz.getName(), true, clazz.getClassLoader());
} catch (ClassNotFoundException e) {
throw new AssertionError(clazz.getName(), e);
}
}
}
}
class Manager {
static {
ClassUtils.forceLoad(A.class);
// ...
}
public static void main(String ...arg) {
// ...
}
}