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

这是我有的代码:

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

和我有的testing,我分开运行。

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

当我运行testingfoo时,我会看到:

 Stupid class loaded! StupidClass 

但是当我运行testing栏时,我所看到的是:

 StupidClass 

从这个网页引用..

类对象由Java虚拟机自动构造,随着类的加载以及对类加载器中的defineClass方法的调用。

所以我的理解是,在testing栏中,愚蠢的类被加载,否则我会看到null我猜? 所以Class对象被创build,因为类本身被加载..

现在从这个页面引用

静态初始化块在JVM(类加载器 – 具体)加载StaticClass(在代码中第一次引用时)时运行。

所以我期待看到“愚蠢的类加载!” 在testing栏中的文字也是如此,但我不是。

同时引用Thinking in Java

Candy,Gum和Cookie中的每个类都有一个静态子句,它是在类首次加载时执行的。

这似乎不是很准确..

我错过了什么?

当JVM(类加载器 – 具体)加载StaticClass(在代码中第一次引用时)时,会运行静态初始化块。

上面的引证是错误的,但这只是一个非常普遍的误解。

  1. 当它被加载时,类没有被初始化 ,而是当一个静态类成员被第一次引用时。 这是由规范精确支配的。

  2. 当类首次引用时,类加载不会发生 ,但是在实现相关的点上。

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

Class.forName在默认情况下初始化类,但是您可以select调用一个需要boolean initialize并提供false的重载。 你会得到没有初始化加载的类。

类加载和初始化是两个不同的东西。 一个类可以被加载,但没有被初始化,直到真的有必要。 静态初始化器仅在正在初始化类<>未加载,“已初始化”

在第一种情况下,当你使用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/] ... 

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