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

时间:2016-08-30 05:52:38

标签: java class reference initialization 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;
        }
    }

代码没有输出。

2 个答案:

答案 0 :(得分:5)

是。调用类方法或实例化实例时,将调用静态初始值设定项。

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

1。创建新实例

public static void main(String[] args) {
    A a = new A();
}

2。调用静态类方法

public static void main(String[] args) {
    int f = A.f();
}

答案 1 :(得分:2)

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

Java Language Specification区分

  • Loading

      

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

  • Linking

      

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

         

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

  • Initialization

      

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

对于大多数情况,加载和链接的确切时间无关紧要,因此规范为JVM实现提供了一些关于确切时间的自由度是没有问题的。只有在错误的情况下,例如当一个类不存在或存在不兼容性(链接或验证错误)时,可能会出现JVM特定的差异,关于引发关联的Error的确切时间。

所以你的问题是针对的,不是加载,而是初始化,因为你正在研究执行static所产生的副作用阶级初始化。

初始化时间为precisely defined

  

§12.4.1。初始化发生时

     

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

     
      
  • T是一个类,并创建了T的实例。
  •   
  • 调用static声明的T方法。
  •   
  • 分配了static声明的T字段。
  •   
  • 使用static声明的T字段,该字段不是常量变量(§4.12.4)。
  •   
  • T是一个顶级课程(§7.6)和一个assert语句(§14.10)词汇量嵌套在T§8.1.3)中被执行。
  •   
     

初始化类时,会初始化其超类(如果它们之前未初始化),以及声明任何默认方法(§8.1.5)的任何超接口(§9.4.3)(如果它们以前没有初始化)。接口的初始化本身不会导致其任何超接口的初始化。

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

当谈到加载而不是初始化时,可能存在细微差别,如this scenario所示。