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));
}
}
所以 我们要注意
当父类构造器中 调用了被子类重写过的方法时,并且通过子类构造器来创建对象 ,由于语言特性 会优先执行父类构造器 ,所以会导致子类的重写方法会优先在子类构造器之前执行,从而导致访问不到正常的值
总结 :
由于语言特性 会优先执行父类构造器 ,子类如果有父类重写的方法,会优先执行子类重写的方法