7

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

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

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

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

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

现在我认为静态块会被执行,但事实并非如此。据我所知,静态块在类加载器加载后立即执行SomeClass类,静态块就会执行。现在到我真正的问题:

不是在我定义该类型的变量后立即加载类吗?. 如果是,为什么不执行静态块?

如果答案是否定的,那么我怎么知道类加载器是否已经加载了一个类以及加载该类的不同可能性(我知道 2:初始化变量和使用静态字段/方法)

4

2 回答 2

5

请参阅此文档:http ://www.javaworld.com/article/2077260/learn-java/learn-java-the-basics-of-java-class-loaders.html

那么什么时候加载类呢?恰好有两种情况:当新的字节码被执行时(例如,FooClass f = new FooClass();)和当字节码对类进行静态引用时(例如,System.out)。

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

所以按照你的例子,在类中添加一个静态字段

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

    static String abc = "abc";
}

SomeClass 被加载到:

SomeClass foo = new SomeClass();

或者

System.out.println(SomeClass.abc);
于 2015-11-19T13:31:48.407 回答
4

是不是在我定义了该类型的变量后立即加载了该类?

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

请参阅此相关问答 -静态类初始化何时发生?- 它列出了所有可以触发初始化的东西。


我如何知道类加载器是否已经加载了一个类以及加载该类的不同可能性(我知道 2:初始化变量和使用静态字段/方法)

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

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

  • 使用客户类加载器,该类加载器会在看到加载类的请求时注意到并执行适当的操作。

实际上将要加载一个类:

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

  • 当需要加载它以链接另一个类时,或

  • 在 JVM 启动时,如果该类被命名为入口点类。

JLS 的第 12 章规定了加载/链接/初始化步骤。


1 - 实际上,需要在链接包含该方法SomeClass的类的同时加载;即在调用包含该本地声明的方法之前。main

于 2015-11-19T13:36:47.233 回答