77

我有 2 个罐子,我们称它们为 a.jar 和 b.jar。

b.jar 依赖于 a.jar。

在一个.jar 中,我定义了一个类,我们称之为StaticClass。在 StaticClass 中,我定义了一个静态块,调用了一个名为“init”的方法:

public class StaticClass {
  static {
    init();
  } 

  public void static init () {
    // do some initialization here
  }
}

在 b.jar 中,我有一个 main,所以在 main 中,我希望 init() 方法已被调用,但实际上没有。我怀疑这是因为 jvm 没有加载 StaticClass,谁能告诉我

  1. 我的结论正确吗?
  2. 什么触发 jvm 加载类?
  3. 如何让静态块自动执行?

谢谢

4

9 回答 9

94

是的你是对的。静态初始化块在 JVM(具体来说是类加载器)加载StaticClass(在代码中第一次引用它时发生)时运行。

您可以通过显式调用来强制调用此方法,StaticClass.init()这比依赖 JVM 更可取。

您还可以尝试使用Class.forName(String)强制 JVM 加载类并调用其静态块。

于 2012-02-03T14:52:15.347 回答
7

是的,你是对的,因为你没有使用StaticClass它,它不是由 vm 加载的,因此init()永远不会执行。

对于您的第二个问题,您可能必须采取艰难的方式并扫描所有可用的类并加载它们。

https://stackoverflow.com/a/3223019/393657

于 2012-02-03T14:51:25.300 回答
5

首先,类加载与类初始化不同。对于任何从 Java 语言规范中寻找解释的人,什么时候执行静态块 - 在这里。

JLS §8.7说:

类中声明的静态初始化程序在类初始化时执行(第 12.4.2 节)。

那么初始化是什么意思呢?让我们参考JLS §12.4.2。这描述了详细的初始化过程。但是JLS §12.4.1点在这里可能更合适。它说:

类或接口类型 T 将在以下任何一项第一次出现之前立即初始化:
  • T 是一个类,并创建了一个 T 的实例。
  • T 是一个类,并且调用了 T 声明的静态方法。
  • 分配了一个由 T 声明的静态字段。
  • 使用了由 T 声明的静态字段,并且该字段不是常量变量(第 4.12.4 节)。
  • T 是一个顶级类(第 7.6 节),并且执行在词法上嵌套在 T(第 8.1.3 节)中的断言语句(第 14.10 节)。
  • 因此,要使静态初始化程序块自动执行,您必须强制执行这些选项之一。

    于 2019-07-19T04:12:09.977 回答
    4

    你是对的,最简单的方法是访问类,例如做一个

    StaticClass.class.newInstance();

    或在您的主要方法中与这方面有关的东西。这将确保类由类加载器加载。

    于 2012-02-03T14:50:34.630 回答
    3

    StaticClass引用您的类(我猜)时执行静态代码。

    因此,如果您创建新实例StaticClass调用其静态方法之一,则应该执行它。

    于 2012-02-03T14:51:00.150 回答
    3

    静态块在加载的类首先被初始化或引用时执行。加载类并不意味着要初始化该类。JVM 类加载是需要关注的不同事项。

    于 2016-11-09T05:30:27.083 回答
    0

    是的,静态初始化程序将在加载类时执行。这通常发生在您第一次访问类加载上下文中的类时。

    于 2012-02-03T14:51:32.213 回答
    0

    在 b.jar 中,主方法类应该扩展该 StaticClass,然后自动调用该静态块和 init()

    于 2013-03-18T12:48:53.023 回答
    -2

    添加更多:

    静态块将在 jvm 加载类时执行。

    在您的示例中,您可以通过实例化类来调用您的init()方法StaticClass

    像 StaticClass staticClass=new StaticClass();

    或者

    StaticClass.class.newInstance(); 这是更优选的

    于 2013-05-20T07:31:50.487 回答