未经初始化不执行静态块

Static block not executed without initialization

我有一个关于静态块的问题:

假设我有一个 class 看起来像这样:

class SomeClass {
    static {
        System.out.println("static block");
    }
}

然后我在某处定义了一个 SomeClass 类型的变量。

public static void main(String args[]) {
    SomeClass foo;
}

现在我以为静态块会被执行,但事实并非如此。据我所知,一旦 classloader 加载 SomeClass class,就会执行静态块。现在回答我真正的问题:

class不是一定义那个类型的变量就加载了吗?。如果是,为什么不执行静态块?

如果答案是否定的,那么我如何知道 class 是否已经被 class 加载程序加载以及 class 有哪些不同的可能性已加载(我知道 2:初始化变量并使用静态 field/method)

参考这个文档:http://www.javaworld.com/article/2077260/learn-java/learn-java-the-basics-of-java-class-loaders.html

So when are classes loaded? There are exactly two cases: when the new bytecode is executed (for example, FooClass f = new FooClass();) and when the bytecodes make a static reference to a class (for example, System.out).

在您的示例中,SomeClass foo; 既不执行 SomeClass 的字节码,也不对 SomeClass 进行静态引用。这就是 class 未加载的原因。

因此,按照您的示例,在 class

中添加一个静态字段
public class SomeClass {
    static {
        System.out.println("static block");
    }

    static String abc = "abc";
}

SomeClass 被加载到:

SomeClass foo = new SomeClass();

System.out.println(SomeClass.abc);

Isn't the class loaded as soon as I define a variable of that type?.

是的,它被加载1,但是它不会因为声明一个变量而被初始化。但是,当您创建该类型的实例或访问该类型的静态字段时,这足以触发初始化,包括静态块的执行。

查看此相关问答 - When does static class initialization happen? - 其中列出了可以触发初始化的所有内容。


How can i know if a class has already been loaded by the class loader and what are the different possibilities to have the class loaded (I know of 2: initializing the variable & using a static field/method)

我能想到的找出 class 何时加载(与初始化不同)的唯一方法是:

  • 打开 JVM 的 class 加载程序消息(使用 -verbose:class),或

  • 使用客户 classloader 注意到,并在看到加载 class.

  • 的请求时做一些适当的事情

一个class实际上要被加载:

  • 当使用 Class.forName 或类似方式显式加载时,或直接调用 classloader,

  • 为了link另一个class或

  • 需要加载它时
  • 在 JVM 启动时,如果 class 被命名为入口点 class。

加载/linking/初始化步骤在Chapter 12 of the JLS中指定。


1 - 事实上,SomeClass 需要在包含 main 方法的 class 是 [ 的同时加载=74=]ed;即在调用包含该局部声明的方法之前。