Java对象的创建及初始化过程

对于学习Java的大家来说应该都知道当我们创建对象时,对象和其实例成员是被一起保存在JVM的堆内存里面的,然后调用构造器对对象实例成员进行初始化,之后再执行程序。但是有时候我们会发现程序的一些执行结果非常令人费解,比如下面的例子:

public class SubClass extends SuperClass{
	int j = 30;
	public SubClass(){
		print();
		j=40;
	}
	public void print(){
		System.out.println(j);
	}
	{j=50;}
	public static void main(String[] args) {
		System.out.println(new SubClass().j);
	}
}

class SuperClass{
	int i=10;
	public SuperClass(){
		print();
		i=20;
	}
	public void print(){
		System.out.println(i);
	}
}

结果:0/50/40

那么大家猜对了吗?为什么第一个会打印出0呢?不是应该是10吗?那么下面我们就了解一下对象的创建及初始化过程吧!

一、Java创建对象的几种情景(假设有一个Person类):


对象被创建以后,JVM会干两件事:

1)在堆内存中为对象和其实例变量分配内存,这里要注意的是,从超类继承下来的实例变量也会被分配内存。

2)为所有实例变量赋默认值,也需要注意的是这里的默认值都是相应类型的零值(引用类型:null,基本数据类型:0/0L/0.0f/0.0等)。

二、对象的初始化过程

当对象创建并赋默认零值后,就可以按照程序员的意志来进行一些初始化了。这里将需要初始化的变量分为三种:

1)类似private int a = 1;的这种定义时就赋值的;

2)类似private int b;{b=5}这种在静态块里面初始化的;

3)构造函数里面初始化的;

Java程序的执行分为:

1)编译期:编译器将.java文件编译成.class文件

2)运行期:JVM加载.class文件并运行.class文件

编译器在编译时会将类的构造方法命名为<init>()方法,只要调用构造器进行实例变量初始化,<init>()方法为被当成一个收集器收集类中的所有实例成员赋值语句(包括普通块{}里面的赋值语句)放到构造器中调用超类构造器的语句之后,其它语句之前,收集顺序依源程序文件代码编写顺序至上而下,然后依次执行。

OK,原理解释完毕,我们来推理一下上面的题目吧:

1)首先,程序先找到main方法,然后加载SubClass类的时候发现SubClassC继承SuperClass类,然后先去加载SuperClass类,再回过头来加载SubClass类;

2)类加载完之后开始执行main方法里面的System.out.println(new SubClass().j),程序看到new关键字先创建一个SubClass对象,为其实例成员赋默认零值;然后调用构造器SubClass(),由于其中隐式调用了超类的构造器,程序转而去执行超类的构造器,之后超类构造器的<init>()方法收集超类实例成员及块赋值语句在放在其构造器里的其它语句前进行初始化;之后再转到自身的构造器利用<init>()方法收集块语句及实例成员赋值语句放在构造器里的其它语句之前进行初始化,之后就是上面的结果了,需要注意的是里面的print()方法涉及到重写的一些知识。有兴趣自己推一下吧!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值