2016-09-15 58 views
68

这是我的代码:为什么.class不能调用类中的静态块?

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

当我运行测试我会看到:

Stupid class loaded! 
StupidClass 

但是当我运行测试酒吧所有我看到的是:

StupidClass 

this页面引用..

类对象是由Java虚拟机 自动构造的,因为在加载类时以及调用类加载器中的defineClass方法 。

所以我的理解是,在测试吧,愚蠢的类被加载,否则我会看到一个空我猜?因此,在创建类对象,因为类本身被加载..

而且现在从this页面引用时,JVM(类加载器 - 以 具体)

静态初始化块运行加载StaticClass(发生第一次是代码中引用的 )。

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

Thinking in Java

另外引述每个类糖果,胶,和曲奇具有静态子句是 作为类被装载在第一次执行。

这是不是很准确,似乎..

我缺少什么?

+0

如果您将两个测试作为一个或分开的进程运行,则应该提及。 –

+0

@DuongNguyen我做过了吗? “和我的测试,我分开运行。” –

+0

我的错误。有趣的问题。我的猜测是这个类在这种情况下还没有真正加载过。 –

回答

59

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

上面的引语显然是错误的,但它只是一个非常普遍的误解的例子。

  1. 未初始化当真实被加载它,但是当一个静态类构件第一次被引用。这是由specification精确治理。

  2. 类加载不会发生当类是第一次引用,但在一个实现相关点。

  3. 当类必须加载的最后时刻是当类被参考,这是不一样作为引用类构件

Class.forName初始化默认的类,但你必须调用一个重载需要boolean initialize和供应false的选择。你会在没有初始化的情况下加载类。

+0

请注意,它必须是一个“静态”成员才能触发类初始化。访问一个实例成员意味着要么是先前的实例化(所以该类已经被初始化),要么是对'null'的访问,它不会触发clazz初始化。这也意味着你可以在不触发接口初始化的情况下调用'interface'方法。 – Holger

+0

我认为“集体成员”暗含静态成员,但你可能是对的。 –

22

类加载和初始化是两件不同的事情。一个类可以被加载,但不会被初始化,直到它真的有必要。静态初始化只运行在一个类被初始化<>未加载,“初始化”

在您加载,当您使用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/] 
... 

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

+0

我相信这涵盖在https://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.1, – nos

+0

@nos - 它应该是覆盖 – TheLostMind

相关问题