在声明引用时是否加载了类?

Mic*_*zyk 3 java initialization reference class loading

创建对类对象的引用是否会导致加载类?加载类时会初始化静态变量,所以考虑到以下代码,答案是否定的,我是对的吗?

    class A{
        static int f(){
            System.out.println("initializing!");
            return 0;
        }
        static final int i = f();
    }
    public class Main {
        public static void main(String[] args) {
            A a;
        }
    }
Run Code Online (Sandbox Code Playgroud)

代码没有输出.

Hol*_*ger 6

将类的加载和初始化视为同一件事是一个常见的错误。

\n

Java语言规范区分了

\n
    \n
  • 加载中

    \n
    \n

    加载是指查找具有特定名称的类或接口类型的二进制形式的过程,可能是通过即时计算,但更常见的是通过检索以前由 Java 编译器从源代码计算的二进制表示形式,并构造,从该二进制形式,一个Class对象来表示类或接口。

    \n
    \n
  • \n
  • 链接

    \n
    \n

    链接是获取类或接口类型的二进制形式并将其组合到 Java 虚拟机的运行时状态中以便执行的过程。类或接口类型始终在链接之前加载。

    \n

    链接涉及三种不同的活动:符号引用的验证、准备和解析。

    \n
    \n
  • \n
  • 初始化

    \n
    \n

    类的初始化static包括执行其初始化程序和类中声明的静态字段(类变量)的初始化程序。
    \n接口的初始化包括执行接口中声明的字段(常量)的初始值设定项。

    \n
    \n
  • \n
\n

对于大多数情况,加载和链接的确切时间并不重要,因此规范为 JVM 实现提供有关确切时间的一些自由度是没有问题的。仅在错误情况下,例如,当类不存在或存在不兼容性(链接或验证错误)时,JVM 特定的差异才会显示出来,涉及Error抛出关联的确切时间。

\n

因此,您的问题的目的不是加载,而是初始化,因为您正在查看类初始化程序的执行所产生的副作用static

\n

初始化的时间是精确定义的

\n
\n

\xc2\xa712.4.1。初始化发生时

\n

类或接口类型 T 将在第一次出现以下任一情况之前立即初始化:

\n
    \n
  • TT是一个类并创建了一个实例。
  • \n
  • static调用由 声明的方法T
  • \n
  • static由声明的字段被T赋值。
  • \n
  • static使用由 声明的字段,T并且该字段不是常量变量 ( \xc2\xa74.12.4 )。
  • \n
  • T是顶级类 ( \xc2\xa77.6 ),并且执行词法嵌套在( \xc2\assert xa78.1.3 ) 中的语句 ( \xc2\xa714.10 )。T
  • \n
\n

当一个类被初始化时,它的超类被初始化(如果它们之前没有被初始化),以及声明任何默认方法( \xc2\xa79.4.3 )的任何超接口( \xc2\xa78.1.5)(如果它们有之前没有被初始化)。接口的初始化本身不会导致其任何超级接口的初始化。

\n
\n

因此,从规范中,您可以得出结论:局部变量的存在永远不会触发初始化。将非值分配给引用类型的变量时null,必须有该类型的先前实例化已触发其初始化。然而,未使用的局部变量没有影响。

\n

当涉及到加载而不是初始化时,可能会存在细微的差异,如本场景所示。

\n


Sil*_*gel 5

是.调用类方法或实例化实例时,将调用静态初始化程序.

从您的示例中,您可以执行以下操作之一:

1.创建新实例

public static void main(String[] args) {
    A a = new A();
}
Run Code Online (Sandbox Code Playgroud)

2.调用静态类方法

public static void main(String[] args) {
    int f = A.f();
}
Run Code Online (Sandbox Code Playgroud)

  • 我花了一分钟才明白“是”是对“答案是否定的,我说得对吗?”的答案。考虑到问题的标题,有“是”。因为答案的第一句话有点不幸。我建议重新措辞,可能完全避免“是”和“否”,仅说明仅声明变量不会触发类初始化的事实。 (2认同)