Java之调用被子类重载的方法

    有一种特殊的重写方法,就是当子类重写父类方法,父类表面上只是调用属于自己的、被子类重写的方法,但随着contex的执行改变,将会变成父类直接调用子类的方法。


public class Animal {
	private String desc;
	public Animal() {
		System.out.println("Animalgouzao"+desc);
		// TODO Auto-generated constructor stub
		this.desc=getDesc();
		System.out.println("Animalgouzao!!!!!"+desc);
		
	}
	public String getDesc(){
		System.out.println("Animal getDesc");
		return "Anmial";
	}
	public String toString(){
		System.out.println("Animal toString");
		return desc;
	}

}

public class Dog extends Animal{
	private String name;
	private double weight;
	public Dog(String name,double weight) {
		// TODO Auto-generated constructor stub
		System.out.println("Doggouzao::::"+name+weight);
		this.name=name;
		this.weight=weight;
		System.out.println("Doggouzao"+name+weight);
	}
	/* (non-Javadoc)
	 * @see Animal#getDesc()
	 */
	@Override
	public String getDesc() {
		// TODO Auto-generated method stub
		System.out.println("DogGetDesc::::"+name+weight);
		return "Dog[name="+name+",weight="+weight+"]";
	}
	

}
public static void main(String[] args) {
		System.out.println(new Dog("xiaohua", 20.5));
}
运行结果如下:
Animalgouzaonull
DogGetDesc::::null0.0
Animalgouzao!!!!!Dog[name=null,weight=0.0]
Doggouzao::::xiaohua20.5
Doggouzaoxiaohua20.5
Animal toString
Dog[name=null,weight=0.0]
根据输出的结果,我们来进行一步步的解析:
程序在执行Dog的时候,会隐式调用父类的无参构造,无参构造里调用的getDesc方法其实不是父类的方法而是Dog子类的方法。此时程序还没有执行子类的构造器方法,所以Dog的实例变量值都保持了默认值。因此Dog的getDesc()方法的返回值就是默认值了。也就是我们看到的结果。然后再去执行Dog的构造方法,程序Dog对象的两个实例变量赋值,只是它的desc的实例变量值为默认值。该程序产生这种输出的原因在于在执行调用父类无参构造的时候调用的getDesc()方法是被子类重写过的方法。这样使得Dog实例变量赋值在getDesc()方法之后执行,因此不能得到它的实例变量值。
要想改变这种情况的话,就避免在父类中调用被子类重写过的方法。这样就保证了对Dog对象的实例变量赋值的语句,在getDesc()方法之前被执行,从而使得getDesc()方法得到实例变量值。


注意:如果父类构造器调用了被子类重写的方法,且通过子类构造器来创建子类对象,调用了父类构造器,就会导致子类的重写方法在子类构造器的所有代码之前执行,从而导致之类重写方法访问不到子类的实例变量值的情形。






你可能感兴趣的:(Java)