类变量的初始化时机

实例变量属于Java类本身,只有当程序初始化该Java类时才会为该类的类变量分配内存空间,并执行初始化.

从程序运行的角度来看,每JVM对一个Java类只初始化一次,因此Java程序每运行一次,系统只为类变量分配一次内存空间,执行一次初始化.

从语法角度来看,程序可以在2个地方对类变量执行初始化:

1)定义类变量时指定初始值;

2)静态初始化块中对类变量指定初始值.

这两种方式的执行顺序与它们在源程序中排列顺序相同.下列程序示范了类变量的初始化时机.

package com.lic.array;

public class Demo11 {

	// 定义count类变量,定义时指定初始值
	static int count = 2;
	// 通过静态初始化块为name类变量指定初始值
	static {
		System.out.println("StaticInitTest的静态初始化块");
		name = "Java编程";
	}
	// 定义name类变量时指定初始值
	static String name = "疯狂Java讲义";
	public static void main(String[] args) {
		// 方位该类的两个类变量
		System.out.println("count类变量的值:"+Demo11.count);
		System.out.println("name类变量的值:"+Demo11.name);
	}

}
控制台输出:

StaticInitTest的静态初始化块
count类变量的值:2
name类变量的值:疯狂Java讲义
上面程序中粗体字代码代表了对类变量的两种初始化方式,包括定义类变量时指定初始值,静态初始化块中为类变量指定初始值.每次运行该程序,系统将会对Demo11类执行初始化:先为所有类变量分配内存空间,再按源代码中的排列顺序执行静态初始化块中所指定的初始值和定义类变量时所指定的初始值.

对于本例程序而言,静态初始化块中对name变量的指定初始值位于定义name变量时指定初始值之前,因此系统先将name类变量赋值为"Java编程",然后再将该name类变量赋值为"疯狂Java讲义".每运行该程序一次,这个初始化过程只执行一次,因此运行上面程序将看到输出name类变量的值为"疯狂Java讲义".

下面程序更清楚地表现了类变量的初始化过程.首先定义了Price类,该Price类里有一个静态的initPrice变量,用于代表初始价格.每次创建Price实例时,系统会以initPrice为基础,减去当前打折价格(由discount参数代表)即得到该Price的currentPrice变量值.

package com.lic.array;

public class Demo12 {

	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);
	}

}
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;
	}
}
控制台输出:

-2.8
17.2
上面程序中两个输出语句都访问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 - discount;
为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.



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zerlinda_Li

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值