探究子类构造器和 父类构造器 的实例变量赋值问题

我们都知道  类的加载  一定是 父类构造器执行 然后是子类构造器 

class Base
{
	// 定义了一个名为i的实例变量
	private int i = 2;
	public Base()
	{
		this.display();
	}
	public void display()
	{
		System.out.println(i);
	}
}
// 继承Base的Derived子类
class Derived extends Base
{
	// 定义了一个名为i的实例变量
	private int i = 22;
	// 构造器,将实例变量i初始化为222
	public Derived()
	{
		i = 222;              // ②
	}
	public void display()
	{
		System.out.println(i);
	}
}
public class Test
{
	public static void main(String[] args)
	{
		// 创建Derived的构造器创建实例
		new Derived();       // ①
	}
}

请猜下最后打印多少呢

 

没猜到吧 

下面 解释一下

当我们new Derived();    时  会给这个对象分配空间,但是会为这个对象分配 2个空间 ,1个是 Base里的i  ,另一个是  Derived里的i ,此时 2个变量都是0,

然后执行父类构造器  但是最终打印了0 ,这是什么鬼,明明调用了 display()这个方法 ,而且Base 的i 已经显示的赋值为2 ,结果打印了0,。 

关于这个 问题关键在于 调用这个方法的this 这个关键字,this 在构造器中表示正在初始化的对象

我们在这个 Base类的构造器中加入这个代码

// 直接输出this.i
System.out.println(this.i)
class Base
{
	// 定义了一个名为i的实例变量
	private int i = 2;
	public Base()
	{
		// 直接输出this.i
		System.out.println(this.i);
		this.display();
	}
	public void display()
	{
		System.out.println(i);
	}
}
// 继承Base的Derived子类
class Derived extends Base
{
	// 定义了一个名为i的实例变量
	private int i = 22;
	// 构造器,将实例变量i初始化为222
	public Derived()
	{
		i = 222;
	}
	public void display()
	{
		System.out.println(i);
	}
}
public class Test2
{
	public static void main(String[] args)
	{
		// 创建Derived的构造器创建实例
		new Derived();
	}
}

此时会输出多少呢 

答案可能都没想到

 

对没错 就是 2,0  为什么 ? 明明这个this 代表的是 Derived对象 为什么会输出 2呢 

因为 this虽然代表 Derived 对象 但是这个呢 是处于 Base构造器中,他的编译时类型 为 Base 

实际指向的是 Derived 对象 

我们验证一下 在 Derived类加上sub()方法

class Base
{
	// 定义了一个名为i的实例变量
	private int i = 2;
	public Base()
	{
		// 直接输出this.i
		System.out.println(this.i);
		this.display();
		// 输出this实际的类型,将看到输出Derived
		System.out.println(this.getClass());
		// 因为this的编译类型是Base,所以依然不能调用sub()方法,
		// this.sub();
	}
	public void display()
	{
		System.out.println(i);
	}
}
// 继承Base的Derived子类
class Derived extends Base
{
	// 定义了一个名为i的实例变量
	private int i = 22;
	// 构造器,将实例变量i初始化为222
	public Derived()
	{
		i = 222;
	}
	public void display()
	{
		System.out.println(i);
	}
	public void sub(){}
}
public class Test3
{
	public static void main(String[] args)
	{
		// 创建Derived的构造器创建实例
		new Derived();
	}
}

 

从这个  this.getClass() 这个方法获取的是Derived对象,但是 我们在Base 构造器中调用sub ()方法时,出现编译不通过的问题 ,原因是这个this 在编译时类型为Base 

总结 

当变量的编译时类型和运行时类型不同时访问他引用的对象实例变量时 ,是由声明该变量的对象类型决定的 比如 Base 里的 this.i   , 但是访问他引用的对象实例方法时,是由变量的实际引用的对象决定的 比如 Base 构造器里调用的 this.sub() 就会在编译时报错

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值