当前位置:编程学习 > JAVA >>

关于构造器内部的多态方法的行为

在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.
这个问题想了两天了,一直是不得其解,希望高人指点迷经.
多态 虚拟机 java 栈 class --------------------编程问答--------------------

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() --------------------编程问答-------------------- 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,后输出

程序流程是这样的,要上升到栈啊、堆啊的就要等大神回复你了 --------------------编程问答-------------------- java 多态内存布局不懂,帮顶 --------------------编程问答--------------------
引用 2 楼 u012047741 的回复:
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,后输出

程序流程是这样的,要上升到栈啊、堆啊的就要等大神回复你了

我就不明白为什么会找到子类的draw(),是如何找到的? --------------------编程问答--------------------
引用 1 楼 soton_dolphin 的回复:

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()

可否在深入点? --------------------编程问答--------------------
引用 4 楼 smallfoxxizo 的回复:
我就不明白为什么会找到子类的draw(),是如何找到的?


也就是java多态的实现原理?嗯,我找了篇文章,你看下
http://www.cnblogs.com/stonehat/archive/2012/04/30/2476798.html

或者你也可以再百度下“java多态原理”,只能帮你到这里了 --------------------编程问答--------------------
引用 5 楼 smallfoxxizo 的回复:
Quote: 引用 1 楼 soton_dolphin 的回复:


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()

可否在深入点?


动态绑定原理如下:

假如一个对象O是class C1, C2,...Cn-1, Cn的实例,其中C1是C2的子类,C2是C3的子类。。。以此类推,Cn-1是Cn的子类,也就是说Cn是最笼统的一个类,而C1是最细致的一个类。 如果实例O调用方法P,JVM就会从C1 - CN 中搜索P的实现,也就是说从最细致的一个类开始搜索直到最笼统的一个类。一旦有一个实现被找到,JVM就会调用P方法的这个实现。 --------------------编程问答--------------------
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行代码,楼主运行一下就知道咯 --------------------编程问答--------------------
引用 8 楼 p312003375 的回复:
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行代码,楼主运行一下就知道咯

在Glyph中的构造函数的this指向的是roundGlyph,那这样的话,与invokevirtual就能对应起来了,我在想这个方法的的this为什么是Roundglyph,是不是类Roundglyph在调用构造函数的时候,会在自己的构造函数中选调用父类的构造函数,这样的话,父类的构造函数在子类中? --------------------编程问答--------------------
引用 9 楼 smallfoxxizo 的回复:
Quote: 引用 8 楼 p312003375 的回复:

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行代码,楼主运行一下就知道咯

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

子类在被实例化的时候首先调用父类的构造方法,你说的是对的;
而这个this为什么指向子类,很简单啊,this代表的是对象实例,在你的代码中Glyph类没有被实例化,仅仅是它的子类被实例化了,所以this才指向roundGlyph类的对象啊。
你看看我加的第4行代码,创建Glyph类对象的运行结果,this不就指向他自己了吗。。。。 --------------------编程问答--------------------
引用 10 楼 p312003375 的回复:
Quote: 引用 9 楼 smallfoxxizo 的回复:

Quote: 引用 8 楼 p312003375 的回复:

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行代码,楼主运行一下就知道咯

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

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

这里面有个问题,子类并没有被实例化 --------------------编程问答--------------------
引用 11 楼 smallfoxxizo 的回复:
Quote: 引用 10 楼 p312003375 的回复:

Quote: 引用 9 楼 smallfoxxizo 的回复:

Quote: 引用 8 楼 p312003375 的回复:

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行代码,楼主运行一下就知道咯

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

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

这里面有个问题,子类并没有被实例化

子类没有实例化,你在搞笑吗?? --------------------编程问答--------------------
引用 12 楼 p312003375 的回复:
Quote: 引用 11 楼 smallfoxxizo 的回复:

Quote: 引用 10 楼 p312003375 的回复:

Quote: 引用 9 楼 smallfoxxizo 的回复:

Quote: 引用 8 楼 p312003375 的回复:

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行代码,楼主运行一下就知道咯

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

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

这里面有个问题,子类并没有被实例化

子类没有实例化,你在搞笑吗??

不是我搞笑,在调用父类构造函数的时候,还没有调用子类的构造函数。 --------------------编程问答--------------------
引用 12 楼 p312003375 的回复:
Quote: 引用 11 楼 smallfoxxizo 的回复:

Quote: 引用 10 楼 p312003375 的回复:

Quote: 引用 9 楼 smallfoxxizo 的回复:

Quote: 引用 8 楼 p312003375 的回复:

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行代码,楼主运行一下就知道咯

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

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

这里面有个问题,子类并没有被实例化

子类没有实例化,你在搞笑吗??

我理解有点问题了,应该是在堆里已分配了空间,初始化成了默认值。
补充:Java ,  Java SE
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,