【Java】【多态】构造器的执行是你想象的那样么?

构造器和多态

构造器的调用顺序

首先,我们知道构造器是为了能够给对象正确的进行初始化赋值使用的,为了能够生成一个正确的对象;如果只是一个类,那么构造器在创建对象的时候调用,不会出现什么匪夷所思的事情,但是如果有了相关的继承关系

基类的构造器总是在导出类的构造过程中被调用,而且按照继承层次逐渐向上链接,以使每个基类构造器都能够得到调用,这样做是非常有意义的,因为导出类只能访问自己的成员,不能访问基类中private类型的成员。所以要保证基类中的属性表现出正确的行为,必须由他的构造器对他们进行初始化操作。

package duotai;

public class Meal {
	Meal(){
		System.out.println("Meal()");
	}
}
//----------------------------------------

package duotai;

public class Bread {
	Bread(){
		System.out.println("Bread()");
	}
}
//----------------------------------------

package duotai;

public class Cheese {
	Cheese(){
		System.out.println("Cheese()");
	}
}
//----------------------------------------

package duotai;

public class Lettuce {
	Lettuce(){
		System.out.println("Lettuce()");
	}
}
//----------------------------------------

package duotai;

public class Lunch extends Meal{
	Lunch(){
		System.out.println("Lunch()");
	}
}
//----------------------------------------

package duotai;

public class PortableLunch extends Lunch {
	PortableLunch(){
		System.out.println("PortableLunch()");
	}
}
//----------------------------------------

package duotai;

public class SandWich extends PortableLunch {
	private Bread b = new Bread();
	private Cheese c = new Cheese();
	private Lettuce l = new Lettuce();
	
	public SandWich() {
		System.out.println("Sandwich()");
	}
	
	public static void main(String[] args) {
		new SandWich();
	}
}
//-------------------------------------------
//output:
Meal()
Lunch()
PortableLunch()
Bread()
Cheese()
Lettuce()
Sandwich()

在final关键字那篇文章里我大概说过了这个过程
final关键字
1、不断反复递归调用基类构造器
2、按声明顺序调用成员的初始化方法
3、调用导出类构造器的主体

//先各个属性,然后是构造器方法中的初始化赋值

构造器内部的多态方法的行为

class Glyph{
	void draw(){ print("Glyph.draw()") }
	Glyph(){
		print("Glyph() before draw()");
		draw();
		print("Glyph() after draw()");
	}
}
//-------------------------------------------

class RoundGlyph extends Glyph{
	private int radius = 1;
	RoundGlyph(int r){
		radius = r;
		print("RoundGlyph.RoundGlyph().radius = " + radius);
	}
	void draw(){
		print("RoundGlyph.draw().radius = " + radius);
	}
}
//-----------------------------------------

public class PolyConstructors{
	public static void main(String[] args){
		new ToundGlyph(5);
	}
}

//output:
Glyph() before draw()
RoundGlyph.draw().radius = 0
Glyph() after draw()
RoundGlyph.RoundGlyph().radius = 5

神奇的事情出现了,第二行打印出来了一个“0”
首先他会递归,调用了Glyph的构造方法,然后在调用构造方法中的draw()的时候,调用了他的重写方法

更详细一点,初始化的实际过程是:

1、将分配给对象的存储空间赋零值
2、调用基类构造器,此时,调用被覆盖后的draw()方法,这个过程是在调用RoundGlyph构造器之前调用的,由于第一步,所以这时候radius的值是0。
3、按照声明的顺序调用成员的初始化方法
4、调用导出类的构造函数主体

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值