探究子类重写父类方法的调用

这篇博客探讨了Java中构造器与方法重写的一个常见陷阱。在创建`Wolf`对象时,由于父类`Animal`的构造器在子类构造器之前执行,`getDesc()`方法被子类重写,导致`desc`变量被意外地初始化为`Wolf[name=null,weight=0.0]`。问题的关键在于父类构造器中调用了可能被子类重写的方法。修复方法是避免在父类构造器中直接调用可能被重写的方法,而是将其封装在`toString()`中,确保在子类构造器完成后再调用。这提醒开发者在设计类时要谨慎处理构造器和方法重写的关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


class Animal
{
	// desc实例变量保存对象toString方法的返回值
	private String desc;
	public Animal()
	{
		// 调用getDesc()方法初始化desc实例变量
		this.desc = getDesc();            // ②
	}
	public String getDesc()
	{
		return "Animal";
	}
	public String toString()
	{
		return desc;
	}
}
public class Wolf extends Animal
{
	// 定义name、weight两个实例变量
	private String name;
	private double weight;
	public Wolf(String name, double weight)
	{
		// 为name、weight两个实例变量赋值
		this.name = name;                 // ③
		this.weight = weight;
	}
	// 重写父类的getDesc()方法
	@Override
	public String getDesc()
	{
		return "Wolf[name=" + name + ", weight="
			+ weight + "]";
	}
	public static void main(String[] args)
	{
		System.out.println(new Wolf("灰太狼", 32.3)); // ①
	}
}

请猜猜会打印多少

没想到吧

我们来看看原因

我们在main 方法中 new Wolf()对象  ,此时 会为这个对象 和变量分配内存,然后给变量设置默认值,这时 在执行 Wolf 构造方法时,由于语言特性 又优先执行 父类的构造方法由于这个父类构造方法里调用的 getDesc() 方法 会变为子类重写的 getDesc() 方法而且此时子类的构造方法并没有执行,所以 子类的2个变量都为默认值,所以父类的desc 变量被赋值为“Wolf[name=null, weight=0.0]” ,等到子类构造方法执行完成 ,此时的 name和 weight 变 赋值为  灰太狼, 32.3

但由于父类的构造器已经执行完成,不会在为  desc 变量 赋值 ,所以还是为“Wolf[name=null, weight=0.0]”

我们改造一下 如何正确使用

class Animal
{
	public String getDesc()
	{
		return "Animal";
	}
	public String toString()
	{
		return getDesc();
	}
}
public class Wolf2 extends Animal
{
	// 定义name、weight两个实例变量
	private String name;
	private double weight;
	public Wolf2(String name, double weight)
	{
		// 为name、weight两个实例变量赋值
		this.name = name;
		this.weight = weight;
	}
	// 重写父类的getDesc()方法
	@Override
	public String getDesc()
	{
		return "Wolf[name=" + name + ", weight="
			+ weight + "]";
	}
	public static void main(String[] args)
	{
		System.out.println(new Wolf2("灰太狼", 32.3));
	}
}

所以 我们要注意

当父类构造器中 调用了被子类重写过的方法时,并且通过子类构造器来创建对象 由于语言特性 会优先执行父类构造器  ,所以会导致子类的重写方法会优先在子类构造器之前执行,从而导致访问不到正常的值 

总结  :

由于语言特性 会优先执行父类构造器 子类如果有父类重写的方法,会优先执行子类重写的方法 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值