为什么.class不会调用类中的静态块?

Kor*_*gay 68 java static initialization class

这是我的代码:

public class StupidClass {
    static {
        System.out.println("Stupid class loaded!");
    }
}
Run Code Online (Sandbox Code Playgroud)

我的测试,我分开运行.

import org.junit.Test;

public class StupidTest {
    @Test
    public void foo() throws ClassNotFoundException {
        final Class<?> stupidClass = Class.forName("StupidClass");
        System.out.println(stupidClass.getSimpleName());
    }

    @Test
    public void bar() throws ClassNotFoundException {
        final Class<StupidClass> stupidClassClass = StupidClass.class;
        System.out.println(stupidClassClass.getSimpleName());
    }
}
Run Code Online (Sandbox Code Playgroud)

当我运行test foo时,我会看到:

Stupid class loaded!
StupidClass
Run Code Online (Sandbox Code Playgroud)

但是,当我运行测试栏时,我看到的是:

StupidClass
Run Code Online (Sandbox Code Playgroud)

这个页面引用..

类对象由Java虚拟机在加载类时自动构造,并通过调用类加载器中的defineClass方法来构造.

所以我的理解是,在测试栏中,Stupid类被加载,否则我会看到一个null我猜?因此创建了Class对象,因为类本身已被加载.

现在引用这个页面

当JVM(类加载器 - 要特定)加载StaticClass(第一次在代码中引用时出现)时,运行静态初始化块.

所以我期待看到"愚蠢的课程加载!" 测试栏中的文字也是,但我不是.

同样引用Thinking in Java

Candy,Gum和Cookie中的每个类都有一个静态子句,该子句在第一次加载类时执行.

这似乎不是很准确..

我错过了什么?

Mar*_*nik 59

当JVM(类加载器 - 要特定)加载StaticClass(第一次在代码中引用时出现)时,运行静态初始化块.

上面的引用是完全错误的,但它只是一个非常普遍的错误观念的一个例子.

  1. 在加载类时,不会初始化类,但是在首次引用静态类成员时.这完全受规范的约束.

  2. 首次引用类时,不会发生类加载,但是在依赖于实现的点上.

  3. 必须加载类的最后一刻是引用类时,这引用类成员不同.

Class.forName默认情况下初始化类,但您可以选择调用带有boolean initialize和提供的重载false.您将在不初始化的情况下加载类.


The*_*ind 22

类加载和初始化是两个不同的事情.可以加载一个类,但在真正需要之前不进行初始化.静态初始化程序仅在初始化类时运行<> NOT loaded,"initialized"

在第一种情况下,您在使用时加载并初始化类class.forName(),这就是静态初始化程序运行的原因,因此您将其"Stupid class loaded!"视为输出.在第二种情况下,你只是分配一个类的引用,该类被加载(使用java -verbose:class来查看加载了哪些类),但你并没有真正初始化它(或者更确切地说,没有做任何迫使初始化程序运行的东西).因此,您不会将输出视为Stupid class loaded!.尝试做类似调用newInstance()类,它应该强制类的初始化,你应该看到Stupid class loaded!

我的代码:

public class CheckPalindrome {

    public static void main(String[] args) {
        Class<Test> t = Test.class;
    }

}
// class being loaded
class Test {
    static {
        System.out.println("aaa");
    }
}
Run Code Online (Sandbox Code Playgroud)

加载的类

...
[Loaded Test from file:/Workspaces/SampleTest/Java8/bin/]
...
Run Code Online (Sandbox Code Playgroud)

^ - 这表明该类已加载但未初始化.