abstract class Shape {
abstract void draw();
Shape() {
System.out.println("Shape() before draw()");
draw();
System.out.println("Sharp() after draw()");
}
}
class Circle extends Shape {
private int radius = 1;
Circle(int r) {
radius = r;
System.out.println("Circle.Circle(), radius = " + radius);
}
void draw() {
System.out.println("Circle.draw(), radius = " + radius);
}
}
public class Sharp {
public static void main(String[] args) {
new Circle(5);
}
}程序运行的结果如下:
Shape() before draw()
Circle.draw(), radius = 0
Sharp() after draw()
Circle.Circle(), radius = 5我主要是不明白这里:Circle.draw(), radius = 0
请高手详细讲解细节的过程,谢谢了。
Circle(int r){}为
Circle(int r){
System.out.println("shape() before draw()");
draw();
System.out.println("shape() after draw()");
radius=5;
System.out.println("Circle.circle(), radius = "+radius);
}
继承如果没有显示调用它就会在第一行代码之前调用父类的默认构造方法!
是初始化顺序决定的
子类构造函数Circle(int r)调用之前要先调用父类的构造函数Shape()
System.out.println("Shape() before draw()");打印Shape() before draw()
draw();
子类重写了draw();方法,所有调用子类的draw()方法
void draw() {
System.out.println("Circle.draw(), radius = " + radius);
}
打印Circle.draw(), radius = 0
因为子类构造函数还没有被调用,radius变量还没有被赋值,此时值为默认值0
首先给Circle对象实例分配内存,进行默认初始化,private int radius = 0;
然后执行父类的构造函数,Shape() {
System.out.println("Shape() before draw()");
draw();
此时多态的调用子类的draw();
void draw() {
System.out.println("Circle.draw(), radius = " + radius);
}
此时的 radius仍然保持器默认值0不变。
接着执行System.out.println("Sharp() after draw()");
父类构造函数执行完毕。
执行子类的构造函数:
radius = r;
System.out.println("Circle.Circle(), radius = " + radius);
执行完毕!
原因是:
new Circle(5) 后会先调用父类的构造方法,父类的构造方法会调用子类的draw方法
此时 子类的属性 radius 初始化为0
Circle(int r) {
super(); //调用父类构造器的这个语句被省略了
radius = r;
System.out.println("Circle.Circle(), radius = " + radius);
}
程序执行的过程是这样,new Circle的时候,走Circle的构造函数,然后就走super(),在父类的构造函数里会调用draw这个方法,而由于多态的原因,此时调用的draw是Circle类里面的draw方法,但是,请注意,new Circle以后第一个走的是Circle构造函数,private int radius这句话还没有走,所以此时调用draw方法的时候radius是一个默认的值0,这也就是楼主见到Circle.draw(), radius = 0 这句话的原因
如果你吧private int radius,改成private static int radius=1那结果就不一样了。
如果还是不明白的话,我建议LZ在程序的 public static void main(String[] args) 这一行设一个断点,然后用debug的方式一步步的跟踪程序,就会明白程序执行的整个流程了。
思路也清晰了许多。
我当时就想:为什么不是打印这个:Circle.draw(), radius = 1
原来是:
进行默认初始化,private int radius = 0当时看到程序:private int radius = 1;的这句话,就想不通了
不过经过你们的讲解,明白了原理了。