为什么我的静态代码块不执行?

4

我正在尝试运行这段代码,但发现final和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类的静态块不运行?

1
请修复您问题中代码的缩进。目前它无法阅读。 - Jon Skeet
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。)

如果您依赖于使用 A.a 来确保类型已初始化,则不应添加无操作方法:

public static void ensureClassIsInitialized() {
} 

然后只需从您的main方法中调用that。尽管如此,需要这样做的情况非常不寻常。


谢谢,我在我的程序中没有这样做,但是在面试中被问到为什么 A 的静态块不会运行... - Sandepp1
是的,但如果int a=9没有使用final,那么静态方法就可以正常执行了,为什么加上final后就无法执行呢...请帮帮我! - Sandepp1
@Sandepp1:如果没有 final,它将不会是一个编译时常量表达式。 - Jon Skeet

1

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

原始类型或字符串类型的变量,如果是final并且初始化为编译时常量表达式(§15.28),则称为常量变量。 变量是否为常量变量可能会涉及到类初始化(§12.4.1)、二进制兼容性(§13.1、§13.4.9)和明确赋值(§16)等方面。

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


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) {
// ...
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接