实例变量的初始化时机

类体内定义的变量被称为成员变量.如果定义该成员变量时没有使用static修饰,该成员变量又被成为非静态变量或实例变量;如果使用了static修饰,则该成员变量又可被成为静态变量或类变量.


对于实例变量而言,它属于Java对象本身,每次程序创建Java对象时都需要为实例变量分配内存空间,并执行初始化.

从程序运行的角度来看,每次创建Java对象都会为实例变量分配内存空间,并对实例变量执行初始化.

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

1.定义实例变量时指定初始值;

2.非静态初始化块中对实例变量指定初始值;

3.构造器中对实例变量指定初始值.

其中第1,2种方式(定义时指定的初始值和非静态初始化块中指定的初始值)比起第3种方式(构造器中指定初始值)更早执行,但第1,2种方式的执行顺序与它们在源程序中的排列顺序相同.

package com.lic.array;

public class Demo09 {

	public static void main(String[] args) {
		Cat cat = new Cat("kitty", 2);
		System.out.println(cat);
		Cat c2 = new Cat("Jerfield", 3);
		System.out.println(c2);
	}

}
class Cat {
	// 定义name,age两个实例变量
	String name;
	int age;
	// 使用构造器初始化name,age两个实例变量
	public Cat(String name, int age){
		System.out.println("执行构造器");
		this.name = name;
		this.age = age;
	}
	{
		System.out.println("执行非静态初始化块");
		weight = 2.0;
	}
	// 定义时指定初始值
	double weight = 2.3;
	public String toString(){
		return "Cat[name="+name+",age="+age+",weight="+weight+"]";
	}
}
控制台输出:

执行非静态初始化块
执行构造器
Cat[name=kitty,age=2,weight=2.3]
执行非静态初始化块
执行构造器
Cat[name=Jerfield,age=3,weight=2.3]
以上代码代表Java对象的3种初始化方式:构造器,初始化块和定义变量时指定的初始值.每当程序调用指定构造器来创建Java对象时,该构造器必然会获得执行的机会.除此之外,该类所包含的非静态初始化块将会获得执行的机会,而且总是在构造器执行之前获得执行.

当程序执行

Cat cat = new Cat("kitty", 2);
创建第一个Cat对象的时候,程序将会先执行Cat类的非静态初始化块,再调用该Cat类的构造器来初始化该Cat实例.执行完该代码后,内存分分配如图;




从图中可以看出,该Cat对象的weight实例变量的值为2.3,而不是初始化块中指定的.这是因为,初始化块中指定初始值,定义weight时指定初始值,都属于对该实例变量执行的初始化操作,它们的执行顺序与在源程序中的排列顺序相同.在本程序中,初始化块中对weight的赋值位于定义weight语句之前,因此程序将先执行初始化块中的初始化操作,执行完成后weight实例变量的值为2.0;然后再执行定义weight时指定的初始值,执行完成后weight实例变量的值为2.3.从这个意义上来看,初始化块中对weight所指定的初始化值每次都将被2.3所覆盖.

当执行代码

Cat c2 = new Cat("Jerfield", 3);

再次创建一个Cat对象时,程序将再一次调用非静态初始化块,相应的构造器来初始化Cat对象.

定义实例变量时指定的初始值,初始化块中为实例变量指定初始值的语句的地位是平等的,当经过编译器处理后,它们都将被提取到构造器中.也就是说,对于类定义中的语句:

double weight = 2.3;

实际上会被分成如下2次执行.

1)double weight;:创建Java对象时系统根据该语句为该对象分配内存.

2)weight = 2.3;:这条语句将会被提取到Java类的构造器中执行.

示例如下.

package com.lic.array;

public class Demo10 {
	// 定义count实例变量,并为之指定初始值
	int count = 20;
	{
		// 初始化块中为count实例变量指定初始值
		count = 12;
	}
	// 定义两个构造器
	public Demo10(){
		System.out.println(count);
	}
	public Demo10(String name){
		System.out.println(name);
	}
}
上面程序定义了一个count实例变量,既在定义该变量时指定了默认初始值,也在非静态初始化块中为该变量指定初始值.这个程序本身已经非常简单了,无需进行太多深入的讲解.

定义实例变量时指定的初始值.初始化块中为实例变量指定的初始值,构造器中为实例变量指定的初始值,三者的作用完全类似,都用于对实例变量指定初始值.经过编译器处理之后,它们对应的赋值语句都被合并到构造器中.在合并过程中,定义变量语句转换得到的赋值语句,初始化块里的语句转换得到的赋值语句,总是位于构造器的所有语句之前;合并后,两种赋值语句的顺序保持它们在源代码中的顺序.


  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Zerlinda_Li

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

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

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

打赏作者

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

抵扣说明:

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

余额充值