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

时间:2016-09-15 07:00:54

标签: java class static initialization

这是我的代码:

public class StupidClass {
    static {
        System.out.println("Stupid class loaded!");
    }
}

我的测试,我单独运行

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());
    }
}

当我运行测试 foo 时,我会看到:

Stupid class loaded!
StupidClass

但是,当我运行测试 bar 时,我看到的只有:

StupidClass

this页面引用..

  

类对象由Java Virtual自动构造   通过调用defineClass方法加载机器作为类   在类加载器中。

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

现在引用this页面

  

静态初始化块在JVM(类加载器 - 到   具体)加载StaticClass(第一次出现时)   在代码中引用。)

所以我期待看到“Stupid类加载!”测试栏中的文字,但我不是。

同时引用Thinking in Java

  

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

看起来不太准确..

我错过了什么?

2 个答案:

答案 0 :(得分:59)

  

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

以上引用是完全错误的,但它只是一个非常普遍的误解的一个例子。

  1. 在加载时未初始化,但首次引用静态类成员时。这完全由specification

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

  4. 必须加载类的最后一刻是引用类时,与引用类成员不一样

  5. Class.forName默认情况下初始化该类,但您可以选择调用需要boolean initialize并提供false的重载。你将在没有初始化的情况下加载类。

答案 1 :(得分:22)

类加载和初始化是两回事。可以加载一个类,但在真正需要之前不进行初始化。静态初始值设定项仅在初始化类时运行&lt;&gt;未加载,“已初始化”

在第一种情况下,当您使用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");
    }
}

已加载的类

...
[Loaded Test from file:/Workspaces/SampleTest/Java8/bin/]
...

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