没有初始化就不执行静态块

Par*_*alo 7 java static-block

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

假设我的班级看起来像这样:

class SomeClass {
    static {
        System.out.println("static block");
    }
}
Run Code Online (Sandbox Code Playgroud)

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

public static void main(String args[]) {
    SomeClass foo;
}
Run Code Online (Sandbox Code Playgroud)

现在我认为静态块将被执行,但事实并非如此.据我所知,只要类加载器加载SomeClass类,就会执行静态块.现在我真正的问题:

一旦我定义了该类型的变量,是不是加载了类?.如果是,为什么不执行静态块?

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

Bon*_*Bon 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";
}
Run Code Online (Sandbox Code Playgroud)

SomeClass加载到:

SomeClass foo = new SomeClass();
Run Code Online (Sandbox Code Playgroud)

要么

System.out.println(SomeClass.abc);
Run Code Online (Sandbox Code Playgroud)


Ste*_*n C 4

当我定义该类型的变量时,类不是会立即加载吗?

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

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


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

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

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

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

实际上将加载一个

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

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

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

加载/链接/初始化步骤在JLS 第 12 章中指定。


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