【问题标题】:Static block not executed without initialization没有初始化就不会执行静态块
【发布时间】:2016-02-21 16:00:03
【问题描述】:

我有一个关于静态块的问题:

假设我有一个如下所示的课程:

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

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

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

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

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

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

【问题讨论】:

  • 编译器可以删除 foo,在这种情况下是 SomeClass 的导入。 Class.forName("... SomeClass") 确实初始化了类。
  • @JoopEggen 啊好的,但是编译器不能在初始化但从未使用过的 foo 时也删除它吗?还是编译器永远不会这样做?
  • 编译器(和运行时)延迟加载类直到需要它们是一种常见的优化。 import 语句是编译器的指令,但不会在运行时执行。我见过这样的环境,只有在执行引用该类的方法时才加载类,而不是在执行不引用该类的其他方法时加载。
  • Class.forName 重载了一个布尔参数来初始化 class;默认为真。初始化 变量 可能足以调用类加载和初始化,即使整个对象都被优化掉了。应该考虑(理想情况下)有不止一个 java 编译器。
  • @ParkerHalo 是的。一个天真的编译器不会删除未使用的变量。

标签: java static-block


【解决方案1】:

请参阅此文档: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);

【讨论】:

  • Ermm .... SomeClass 类已>>加载>初始化
【解决方案2】:

是不是在我定义了该类型的变量后就加载了该类?

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

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


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

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

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

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

一个类实际上会被加载

  • 使用Class.forName 或类似方法显式加载,或直接调用类加载器时,

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

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

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


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

【讨论】:

    猜你喜欢
    • 2014-05-19
    • 2011-01-26
    • 1970-01-01
    • 1970-01-01
    • 2011-01-12
    • 1970-01-01
    • 1970-01-01
    • 2017-08-16
    • 1970-01-01
    相关资源
    最近更新 更多