在java编程思想这本书中有一小节讲:构造器内部的多态方法行为,源码如下:class Glyph{
   void draw(){syste.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.RoundGLyph(), radius = " + radius);
  }    void draw(){      system.out.println("RoundGlyph.draw(), radius = " + radius);
   }}
public class RolyConstructors {
   public static void main(string[] args){
   new RoundGlyph(5);
   }
}
输出的结果如下:
Glyph() after draw()
RoundGlyph.draw(), radius = 0;
Glyph() after draw()
RoundGlyph.RoundGlyph(), radius = 5在类Glyph的构造函数中调用了一个draw()方法,这个方法的调用最终是指向了子类RoundGlyph中的draw()方法,调用这个方法用的字节码指令为invokevirtual,在<深入理解java虚拟机>(周志明)这本书中写到了多态的本质是invokevirtual调用的方法在运行时会找到操作数栈的第一元素所指的实际类型.那么在本段代码中,类Glyph的构造函数中调用draw()方法的时候,是怎么指向RoundGlyph类的?,操作数栈顶第一个元素指是什么?我只知道在局部变更表的第一个元素是this.
这个问题想了两天了,一直是不得其解,希望高人指点迷经.
多态虚拟机javaclass

解决方案 »

  1.   


    class Glyph{
       void draw(){syste.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){
        super() // compiler 自动加载call父类的构造器
        radius = r;
        system.out.println("RoundGlyph.RoundGLyph(), radius = " + radius);
      } 
     
       void draw(){
          super.draw() // 调用父类的draw()方法
          system.out.println("RoundGlyph.draw(), radius = " + radius);
       }
     
    }
     
     
    public class RolyConstructors {
       public static void main(string[] args){
       new RoundGlyph(5);
       }
    }
    因为 draw() 方法被overridden, 所以会调用子类的draw()
      

  2.   

    Glyph() before draw()
    RoundGlyph.draw(), radius = 0
    Glyph() after draw()
    RoundGlyph.RoundGLyph(), radius = 5
    首先运行结果是上面的这个……
    new RoundGlyph(5);
    1.这段代码运行时会先访问其父类 Glyph的构造函数:
    System.out.println("Glyph() before draw()"); 打印输出
    2.然后draw();会执行被子类RoundGlyph覆写的draw()方法
    此时radius还没有被赋初值,默认为0,因此打印出 RoundGlyph.draw(), radius = 0
    3.继续执行之后的System.out.println("Glyph() after draw()"); 打印输出
    4.父类的构造函数结束,执行本类RoundGlyph的构造函数
    radius = r;
    System.out.println("RoundGlyph.RoundGLyph(), radius = " + radius);
    给radius赋值5,后输出程序流程是这样的,要上升到栈啊、堆啊的就要等大神回复你了
      

  3.   

    我就不明白为什么会找到子类的draw(),是如何找到的?
      

  4.   


    也就是java多态的实现原理?嗯,我找了篇文章,你看下
    http://www.cnblogs.com/stonehat/archive/2012/04/30/2476798.html或者你也可以再百度下“java多态原理”,只能帮你到这里了
      

  5.   

    可否在深入点?动态绑定原理如下:假如一个对象O是class C1, C2,...Cn-1, Cn的实例,其中C1是C2的子类,C2是C3的子类以此类推,Cn-1是Cn的子类,也就是说Cn是最笼统的一个类,而C1是最细致的一个类。 如果实例O调用方法P,JVM就会从C1 - CN 中搜索P的实现,也就是说从最细致的一个类开始搜索直到最笼统的一个类。一旦有一个实现被找到,JVM就会调用P方法的这个实现。
      

  6.   

    class Glyph{
       void draw(){System.out.println("Glyph.draw()");}
       
       Glyph(){
        System.out.println("Glyph() before draw()");
        System.out.println(this.getClass()); //1111111
        this.draw(); //2222222 加了this
        System.out.println("Glyph() after draw()");
       }
    }class RoundGlyph extends Glyph {  private int radius = 1;
      
      RoundGlyph(int r){
        radius = r;
        System.out.println("RoundGlyph.RoundGLyph(), radius = " + radius);
      }    void draw(){      System.out.println("RoundGlyph.draw(), radius = " + radius);
       }}public class RolyConstructors {
       public static void main(String[] args){
       new RoundGlyph(5);
       System.out.println("-------------------------");//333333
       new Glyph(); //444444
       }
    }
    加了4行代码,楼主运行一下就知道咯
      

  7.   

    在Glyph中的构造函数的this指向的是roundGlyph,那这样的话,与invokevirtual就能对应起来了,我在想这个方法的的this为什么是Roundglyph,是不是类Roundglyph在调用构造函数的时候,会在自己的构造函数中选调用父类的构造函数,这样的话,父类的构造函数在子类中?
      

  8.   

    在Glyph中的构造函数的this指向的是roundGlyph,那这样的话,与invokevirtual就能对应起来了,我在想这个方法的的this为什么是Roundglyph,是不是类Roundglyph在调用构造函数的时候,会在自己的构造函数中选调用父类的构造函数,这样的话,父类的构造函数在子类中?
    子类在被实例化的时候首先调用父类的构造方法,你说的是对的;
    而这个this为什么指向子类,很简单啊,this代表的是对象实例,在你的代码中Glyph类没有被实例化,仅仅是它的子类被实例化了,所以this才指向roundGlyph类的对象啊。
    你看看我加的第4行代码,创建Glyph类对象的运行结果,this不就指向他自己了吗。
      

  9.   

    在Glyph中的构造函数的this指向的是roundGlyph,那这样的话,与invokevirtual就能对应起来了,我在想这个方法的的this为什么是Roundglyph,是不是类Roundglyph在调用构造函数的时候,会在自己的构造函数中选调用父类的构造函数,这样的话,父类的构造函数在子类中?
    子类在被实例化的时候首先调用父类的构造方法,你说的是对的;
    而这个this为什么指向子类,很简单啊,this代表的是对象实例,在你的代码中Glyph类没有被实例化,仅仅是它的子类被实例化了,所以this才指向roundGlyph类的对象啊。
    你看看我加的第4行代码,创建Glyph类对象的运行结果,this不就指向他自己了吗。
    这里面有个问题,子类并没有被实例化
      

  10.   

    在Glyph中的构造函数的this指向的是roundGlyph,那这样的话,与invokevirtual就能对应起来了,我在想这个方法的的this为什么是Roundglyph,是不是类Roundglyph在调用构造函数的时候,会在自己的构造函数中选调用父类的构造函数,这样的话,父类的构造函数在子类中?
    子类在被实例化的时候首先调用父类的构造方法,你说的是对的;
    而这个this为什么指向子类,很简单啊,this代表的是对象实例,在你的代码中Glyph类没有被实例化,仅仅是它的子类被实例化了,所以this才指向roundGlyph类的对象啊。
    你看看我加的第4行代码,创建Glyph类对象的运行结果,this不就指向他自己了吗。
    这里面有个问题,子类并没有被实例化
    子类没有实例化,你在搞笑吗??
      

  11.   

    在Glyph中的构造函数的this指向的是roundGlyph,那这样的话,与invokevirtual就能对应起来了,我在想这个方法的的this为什么是Roundglyph,是不是类Roundglyph在调用构造函数的时候,会在自己的构造函数中选调用父类的构造函数,这样的话,父类的构造函数在子类中?
    子类在被实例化的时候首先调用父类的构造方法,你说的是对的;
    而这个this为什么指向子类,很简单啊,this代表的是对象实例,在你的代码中Glyph类没有被实例化,仅仅是它的子类被实例化了,所以this才指向roundGlyph类的对象啊。
    你看看我加的第4行代码,创建Glyph类对象的运行结果,this不就指向他自己了吗。
    这里面有个问题,子类并没有被实例化
    子类没有实例化,你在搞笑吗??
    不是我搞笑,在调用父类构造函数的时候,还没有调用子类的构造函数。
      

  12.   

    在Glyph中的构造函数的this指向的是roundGlyph,那这样的话,与invokevirtual就能对应起来了,我在想这个方法的的this为什么是Roundglyph,是不是类Roundglyph在调用构造函数的时候,会在自己的构造函数中选调用父类的构造函数,这样的话,父类的构造函数在子类中?
    子类在被实例化的时候首先调用父类的构造方法,你说的是对的;
    而这个this为什么指向子类,很简单啊,this代表的是对象实例,在你的代码中Glyph类没有被实例化,仅仅是它的子类被实例化了,所以this才指向roundGlyph类的对象啊。
    你看看我加的第4行代码,创建Glyph类对象的运行结果,this不就指向他自己了吗。
    这里面有个问题,子类并没有被实例化
    子类没有实例化,你在搞笑吗??
    我理解有点问题了,应该是在堆里已分配了空间,初始化成了默认值。