Java中类变量的初始化时机

Java 1686℃

类变量属于Java类本身,只有当程序初始化该Java 类时才会为该类的类变量分配内存空间,并执行初始化。 从程序运行的角度来看,每 JVM对一个 Java 类只初始化一次,因此 Java 程序每运行一次,系统只为类变量分配一次内存空间,执行一次初始化。 从语法角度来看,程序可以在2个地方对类变量执行初始化:

  • 定义类变量时指定初始值;
  • 静态初始化块中对类变量指定初始值。

这两种方式的执行顺序与它们在源程序中排列顺序相同。下面程序更清楚地表现了类变量的初始化过程。首先定义了 Price 类,该 Price 类里有一个静态的 initPrice变量,用于代表初始价格。每次创建Price实例时,系统会以 initPrice 为基础,减去当前打折价格(由discount 参数代表)即得到该Price 的currentPrice变量值。

class Price 
{ 
      // 类成员是 Price实例 
      final static Price INSTANCE = new Price(2.8); 
      // 再定义一个类变量 
      static double initPrice = 20; 
      // 定义该 Price 的 currentPrice实例变量 
      double currentPrice; 
      public Price(double discount) 
      { 
            // 根据静态变量计算实例变量 
            currentPrice = initPrice - discount; 
      } 
      public static void main(String[] args) 
      { 
            // 通过 Price 的 INSTANCE 访问 currentPrice实例变量 
            System.out.println(Price.INSTANCE.currentPrice);         //① 
            // 显式创建 Price实例 
            Price p = new Price(2.8); 
            // 通过显式创建的Price 实例访问 currentPrice 实例变量 
            System.out.println(p.currentPrice);              //② 
      } 
}

上面程序中①、②行代码都访问 Price 实例的 currentPrice 实例变量,而且程序都是通过new Price(2.8);来创建Price实例的。表面上看,程序输出两个Price 的currentPrice 都应该返回17.2(由20减去 2.8 得到),但实际上运行程序并没有输出两个17.2,而是输出-2.8 和 17.2。 如果仅仅停留在代码表面来看这个问题,往往很难得到正确的结果,下面将从内存角度来分析这个程序。第一次用到 Price 类时,程序开始对 Price 类进行初始化,初始化分成以下2个阶段。

  • (1) 系统为Price 的两个类变量分配内存空间。
  • (2) 按初始化代码(定义时指定初始值和初始化块中执行初始值)的排列顺序对类变量执行初始化。

初始化第一阶段,系统先为 INSTANCE、initPrice 两个类变量分配内存空间,此时INSTANCE、initPrice 的值为默认值 null 和 0.0。接着初始化进入第二个阶段,程序按顺序依次为 INSTANCE、initPrice 进行赋值。对 INSTANCE 赋值时要调用 Price(2.8),创建Price 实例,此时立即执行程序中粗体字代码为currentPrice进行赋值,此时 initPrice类变量的值为0,因此赋值的结果是 currentPrice 等于−2.8。接着,程序再次将 initPrice 赋为 20,但此时对INSTANCE的currentPrice实例变量已经不起作用了。当Price类初始化完成后,INSTANCE类变量引用到一个currentPrice为−2.8的Price实例,而 initPrice类变量的值为 20.0。当再次创建Price 实例时,该Price实例的currentPrice实例变量的值才等于 20.0 – discount。

转载请注明:零五宝典 » Java中类变量的初始化时机