为什么.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(在代码中第一次引用时)时,会运行静态初始化块。
上面的引证是错误的,但这只是一个非常普遍的误解。
-
当它被加载时,类没有被初始化 ,而是当一个静态类成员被第一次引用时。 这是由规范精确支配的。
-
当类首次引用时,类加载不会发生 ,但是在实现相关的点上。
-
类必须被加载的最后一刻是被引用的类,这与引用类成员是不一样的 。
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/] ...
^ – 这表明该类已加载但未初始化。