没有初始化就不执行静态块

时间:2015-11-19 13:19:43

标签: java static-block

我对静态块有疑问:

假设我的班级看起来像这样:

class SomeClass {
    static {
        System.out.println("static block");
    }
}

我在某处定义了SomeClass类型的变量。

public static void main(String args[]) {
    SomeClass foo;
}

现在我认为静态块会被执行,但事实并非如此。据我所知,只要类加载器加载SomeClass类,就会执行静态块。现在回答我真正的问题:

一旦我定义了该类型的变量,是不是加载了类?。如果是,为什么不执行静态块?

如果答案应该是no,那么我怎么知道类加载器是否已经加载了一个类以及加载类的不同可能性(我知道2:初始化变量& using a静态字段/方法)

2 个答案:

答案 0 :(得分:5)

请参阅此文档:http://www.javaworld.com/article/2077260/learn-java/learn-java-the-basics-of-java-class-loaders.html

  

那么什么时候加载类?恰好有两种情况:执行新字节码时(例如,FooClass f = new FooClass();)以及当字节码对类进行静态引用时(例如,System.out)。

在您的示例中,SomeClass foo;既不执行SomeClass的字节码,也不对SomeClass进行静态引用。这就是没有加载课程的原因。

所以按照你的例子,在类

中添加一个静态字段
public class SomeClass {
    static {
        System.out.println("static block");
    }

    static String abc = "abc";
}

SomeClass加载在:

SomeClass foo = new SomeClass();

或者

System.out.println(SomeClass.abc);

答案 1 :(得分:4)

  

一旦我定义了那种类型的变量,是不是加载了类?

是的,它已加载 1 ,但由于声明变量,它不会被初始化。但是,当您创建该类型的实例或访问该类型的静态字段时,这足以触发初始化,包括执行静态块。

请参阅此相关的问与答 - When does static class initialization happen? - 其中列出了可以触发初始化的所有内容。

  

我如何知道类加载器是否已经加载了类以及加载类的不同可能性(我知道2:初始化变量&使用静态字段/方法)

我能想到的唯一方法是找出加载类的时间(与初始化不同):

  • 打开JVM的类加载器消息(使用-verbose:class)或

  • 使用客户类加载器注意,并在看到加载类的请求时执行适当的操作。

一个类实际上将加载

  • 使用Class.forName或类似内容明确加载,或直接调用类加载器时,

  • 当需要加载它以链接另一个类时,或

  • 在JVM启动时,如果该类被命名为入口点类。

加载/链接/初始化步骤在Chapter 12 of the JLS中指定。

1 - 实际上,SomeClass需要在包含该main方法的类链接的同时加载;即在调用包含该本地声明的方法之前。