4

我正在尝试运行此代码,但发现 final with static 的这种行为:代码运行时没有执行 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类的静态块不运行?

4

3 回答 3

7

问题是它A.a是一个常量变量

原始类型或 String 类型的变量,它是 final 并使用编译时常量表达式(第 15.28 节)进行初始化,称为常量变量。

因此,您的方法完全Manager.main按照以下方式编译:

public static void main(String ...arg) {
    System.out.println("main");
    System.out.println(9);
}

不再有真正的引用A.a,因此A该类甚至不需要存在,更不用说初始化了。(您可以删除A.class并仍然运行Manager。)

如果您依靠 usingA.a来确保类型已初始化,则不应添加 no-op 方法:

public static void ensureClassIsInitialized() {
} 

然后从你的方法中调用它。main不过,需要这样做是非常不寻常的。

于 2013-03-19T20:05:57.983 回答
1

规范http://docs.oracle.com/javase/specs/jls/se7/jls7.pdf 第 4.12.1 节说,

原始类型或 String 类型的变量,它是 final 并使用编译时常量表达式(第 15.28 节)初始化,称为常量变量。变量是否为常量变量可能对类初始化(§12.4.1)、二进制兼容性(§13.1、§13.4.9)和明确赋值(§16)有影响。

由于您只访问常量,因此不需要类初始化。

于 2013-03-19T20:29:31.830 回答
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) {
// ...
  }
}
于 2015-06-09T21:11:05.487 回答