请问java高手,有谁能解释一下下面的输出结果?

public class Shape {
private int i = 10;

public Shape() {
i = 20;
print();
}
public Shape(int m) {
i = m;
print();
}
public void print() {
System.out.println("This shape=>" + i);
}
}

public class Circle extends Shape {
private int i = 20;
publi cvoid print() {
System.out.println("this circle=>" + i);
}
public Circle() {
this.i = 30;
print();
super.print();
}
public static void main(String[] args) {
Shape shap = newCircle();

}
}
正确输出结果为:
this circle=>0
this circle=>30
This shape=>20
为什么不是下面的结果:
this circle=>20
this circle=>30
This shape=>20

一楼说的也挺好,但是我估计你还是没明白.


其实这是创建对象的执行流程你没有弄明白,产生结果的原因很简单主要疑虑就是第一个值嘛,你看下面的解释


    创建Circle对象,准备执行Circle构造函数,

    发现有继承关系,先执行父类构造函数,

    执行构造函数之前,检查属性赋值状态,给父类当前属性i赋值10

    执行构造函数,给父类当前属性i赋值20,执行print()

    这里要注意,因为子类Circle重载了print()方法,所以此处调用的不是基类本身的print(),而是去执行了子类的print()由于子类属性i此时还没有执行过赋值操作(执行时发现有父类,优先跳转到父类执行父类的构造函数),所以输出时i只有默认值0

    那么父类构造函数执行完毕后,返回执行子类构造函数

    所以最终结果就为 0 30 20

追问

但是子类执行构造是,先执行this.i = 30;,后执行print();为什么i的值还是0呢?

追答

不,你没细看我说的,子类在准备执行自己的构造函数时,发现了继承关系,这时子类的构造函数不会执行,会优先执行父类构造函数

温馨提示:内容为网友见解,仅供参考
第1个回答  2015-03-19
这真是个棘手的问题啊。。。你要是想得到子类的20,将子类的定义为static,要是想得到父类的20,把print方法里的i改成super.i。。还是我来说吧。。为什么是这个结果,先来想一下这段代码具体的执行过程,在执行开始,先要寻找到main方法,因为main方法是程序的入口,但是在执行main方法之前,必须先加载Circle 类,而在加载Circle 类的时候发现Circle 类继承自Shape类,因此会转去先加载Shape类,在Shape类加载完成之后,便继续加载Circle 类,在加载完所需的类之后,便开始执行main方法。在main方法中执行new Circle ()的时候会先调用父类的构造器,然后再调用自身的构造器。因此,便出现了上面的输出结果。你可以在this.i = 30;下面System.out.println(i);运行你会发现打印的结果会在this circle=>0这句下面
第2个回答  2015-03-19
因为你子类构造器Circle(){}里,第一行会默认调用父类的无参构造器(如果你显示调用了super().print(X)这样的构造器的话,系统就不会调用父类的无参构造器了)追问

我有点不明白:为什么显示调用了super().print(X)这样的构造器的话,系统就不会调用父类的无参构造器了呢?子类不是一定要调用父类的构造函数吗,即使没有显示调用super().print(X),应该也要调用父类构造吧?

相似回答