public class Test2 {
public static void main(String[] args) {
new RoundGlyph(5);
}
}class Glyph { void draw() {
System.out.println("Glyph draw()");
} Glyph() {
System.out.println("Glyph before draw();");
draw();
System.out.println("Glyph after draw();");
}
}class RoundGlyph extends Glyph {
private int radius = 1; RoundGlyph(int r) {
radius = r;
System.out.println("RoundGlyph(),radius:" + radius);
} void draw() {
System.out.println("RoundGlyph.draw(),radius:" + radius);
}
}
打印结果:Glyph before draw(); 
RoundGlyph.draw(),radius:0           //这里,为什么调用的是子类的方法呢?
Glyph after draw(); 
RoundGlyph(),radius:5
谢谢各位了,这边搞不明白.

解决方案 »

  1.   

    这个应该是多态吧,调用哪个draw方法,跟this的具体类型有关吧
      

  2.   

    RoundGlyph子类重写了Glyph父类的draw方法,当继承的时候子类可以假设拥有一个父类的(看不见)引用,当要用到父类的一切方法都会通过这个引用调用,如果子类重写的父类的方法,这个引用就不会指向父类的方法,而是重写后的方法。只要子类重写父类的方法总是调用重写后的。
      

  3.   

    这个问题没法一两句跟你说清楚,LZ试着
    class Glyph {    void draw() { //尝试2,在这个方法前面加上 private
            System.out.println("Glyph draw()");
        }    Glyph() {
            System.out.println(this.getClass()); //尝试1,打印对象的类型,看看到底是什么对象
            System.out.println("Glyph before draw();");
            draw();
            System.out.println("Glyph after draw();");
        }
    }从尝试1可以知道,new RoundGlyph(5);生成的是RoundGlyph对象,如果子类重写了父类的方法,那么调用的就是子类的方法
    LZ可以用javap -verbose Glyph 来查看一下Glyph的执行指令,
    LZ可以找到如下的指令
    invokevirtual #?                  // Method draw:()V
    也就是说,父类在编译的时候,draw方法被编译为一个由virtual-table虚拟表管理的方法(也就是编译为invokevirtual指令),程序执行的时候,会从virtual-table虚拟表中找到实际的方法地址,然后才真正调用方法
    子类重写父类方法后,虚拟表里保存的只有子类的方法,所以从虚拟表中找到的是子类的方法从尝试2可以知道,尽管new RoundGlyph(5);生成的是RoundGlyph对象,调用的也是父类的draw方法
    LZ可以用javap -verbose Glyph来再次查看编译后的指令,
    LZ可以找到如下的指令
    invokespecial #?                  // Method draw:()V
    因为private是不可以重写的,所以父类在编译的时候,draw方法将不再编译为virtual-table虚拟表管理的方法(也就是编译为invokespecial指令),所以程序执行的时候,直接从父类中找到方法的地址,然后调用方法,也就是说,程序执行的是父类本身的方法大概就这么个意思了,LZ慢慢领悟吧