黑马程序员技术交流社区

标题: 关于继承 [打印本页]

作者: 李宁    时间: 2013-1-21 18:02
标题: 关于继承
本帖最后由 shaohuashang 于 2013-1-21 19:51 编辑
  1. class B{
  2.        private int radius = 10;

  3.        public void draw(){
  4.             System.out.println("B.draw,radius = "+radius);
  5.        }

  6.        public B(){
  7.              System.out.println("B constructor");
  8.               draw();这里为什么调用的是子类的draw()而不是父类的?
  9.         }
  10. }

  11. public class A extends B{
  12.         private int radius = 1;

  13.         public void draw(){
  14.             System.out.println("A.draw(),radius = "+radius);
  15.         }
  16.         
  17.         public A(int radius){
  18.             this.radius = radius;
  19.             System.out.println("A contructor");
  20.         }

  21.         public static void main (String[] args){
  22.                 A a = new A(5);
  23.         }
  24. }
复制代码
最后输出的的是
B constructor
A.draw(),radius = 0   不明白结果为什么是0,不是1也不是5
A contructor
在网上看到的一个题,不明白为什么输出的是这个
作者: 王少雷    时间: 2013-1-21 18:10
A a = new A(5);
开了A的空间
首先没指定 调用哪个构造函数,直接默认调父类无参构造。
然后又传一个5进去,调用int radius这个构造 ,把值给指向了5
输出一句里面的A contructor
作者: 柴乔军    时间: 2013-1-21 18:21
本帖最后由 柴乔军 于 2013-1-21 18:26 编辑
  1. public A(int radius){

  2.             super();  //这里其实调用了父类的空参构造函数
  3.             this.radius = radius;

  4.             System.out.println("A contructor");

  5.         }

复制代码
在调用父类构造方法的时候,还没有对子类的radius赋值,int类型的初始值是0,而此时父类的构造方法又调用了draw方法
所以就会输出0 了,调用的子类的draw方法,是因为你创建的是一个子类对象,而子类中又重写了父类的方法,所以调用的自然就是子类的方法
作者: 柴乔军    时间: 2013-1-21 18:40
这种题。。。太隔了。。。
作者: 张云杰    时间: 2013-1-21 18:57
代码执行顺序是这样的 ,  首先A继承B, B是父类, 通常情况下 子类被调用, 父类的构造函数一定会先执行..  所以先执行的是Public B方法  然后 B方法里有个draw();  draw方法被子类重写, 根据概念, 重写一定调用子类, 所以是 子类的draw, 但是, 这时候我们还没有真正跳出父类的构造函数, 因为draw的方法还没执行完..  所以 这时候 int radius 是个空值, 默认 int 空值就是0,  然后打印出0后 跳出父类的构造函数.. 接着 执行子类的方法..  传进去一个5 打印出最后一个...  这道题 重点就是 父类里的子类方法..  执行的时候 由于是在父类的构造方法里, 子类方法没有被真正意义上的调用.. 所以 子类里的值没有传进去.. 多看点书吧.. 书上都有写呢
作者: 张云杰    时间: 2013-1-21 19:03
再说白点.. 这个int 并没有被初始化.. 懂了没? 方法没跳出 没有被初始化.. 所以 int 默认 为0
作者: 苏克    时间: 2013-1-21 19:09
这种题要顺着一步一步往上捣才行。
作者: vmvm555    时间: 2013-1-21 19:23
我终于想通了,从某个方面来说,这题是有一点嗝
  1. class B{
  2.        private int radius = 10;

  3.        public void draw(){
  4.             System.out.println("B.draw,radius = "+radius);
  5.        }

  6.        public B(){                        //第一步
  7.              System.out.println("B constructor");
  8.               draw();这里为什么调用的是子类的draw()而不是父类的?                //因为子类将其覆写了
  9.         }
  10. }

  11. public class A extends B{
  12.         private int radius = 1;

  13.         public void draw(){                //第二步,父类调用子类覆写的方法
  14.             System.out.println("A.draw(),radius = "+radius);        //第三步,打印这句话,为什么会是0呢,执行到这一步,子类的构造方法语句还没有执行,对象还没有初始化,
  15.         }
  16.         
  17.         public A(int radius){
  18.                                                                         //这里有一个Super(),调用父类的空参数构造方法
  19.             this.radius = radius;
  20.             System.out.println("A contructor");
  21.         }

  22.         public static void main (String[] args){
  23.                 A a = new A(5);
  24.         }
  25. }
复制代码
面性对象的基础要打好啊
作者: 李宁    时间: 2013-1-21 19:50
我以为draw()方法在父类的构造方法里面就调用父类,看来是错了
作者: 黑马-小龙    时间: 2013-1-21 20:46
已经被重写的方法,调用的当然是重写后的方法了
作者: 刘军亭    时间: 2013-1-21 20:59
class B{
       private int radius = 10;              //3.成员变量显示初始化

       public void draw(){
            System.out.println("B.draw,radius = "+radius);
       }

       public B(){                        //4.父类初始化
             System.out.println("B constructor");
              draw();这里为什么调用的是子类的draw()而不是父类的?                //因为子类将其覆写了,省略了this关键字
        }
}

public class A extends B{
        private int radius = 1;//6.成员变量显示初始化

        public void draw(){                //5.父类调用子类覆写的方法
            System.out.println("A.draw(),radius = "+radius);        //第三步,打印这句话,为什么会是0呢,执行到这一步,子类的构造方法语句还没有执行,对象还没有初始化,
        }
        
        public A(int radius){
            super();  //2.这里有一个Super(),用A类的对象this,调用父类的空参数构造方法
            this.radius = radius;   //7.对成员变量初始化
            System.out.println("A contructor");
        }

        public static void main (String[] args){
                A a = new A(5);                                         //1.new A的对象
        }
}
作者: 谢毅    时间: 2013-1-21 21:02
A a到这里的时候发生了什么?子类A被分析成字节码放到了虚拟机,接着父类B也被分析成字节码放到了虚拟机,然后虚拟机检测子类与父类的依赖程度,也就是有无重写。
new A(5)这里又发生了什么?虚拟机中的字节码生成子类的默认构造函数对象接着实例对象newInstace(),由于不管子类有无重写,子类与父类有基本的依赖,所以在newInstance()前会先调用父类的构造函数,这里一般为隐式(super()),这个super则是虚拟机通过子类的字节码对象getSuperClass()找到的,所以父类的构造函数执行到draw()的时候通过先前的检测这里就调用了子类的draw(),子类的draw()执行到radius的时候子类这时还没进行newInstance(),所以为默认值0
A a = new A(5)用个模糊流程来模拟下:
    Class.forName("A");//只是描述了内存中的状态
    Class.forName("B");//同上
    Constructor c1 = Class.forName("A").getConstructor(int.class);
    c1.newInstance(5);//这里我猜虚拟机在这里打了个标记,暂不执行,紧接着执行下面的代码
    Class clazz = Class.forName("A").getSuperClass();
    Constructor c2 = clazz.getConstructor();
    c2.newInstance();//这里执行完后虚拟机就返回刚才的标记那里继续执行

     
作者: 高浩    时间: 2013-1-21 22:04
class B{
       private int radius = 10;                                                                        存在了继承关系,如果调用子类构造函数,顺序是这样
       public void draw(){                                                                             子类里面有一条隐式的父类构造函数会先调用它,而B类
            System.out.println("B.draw,radius = "+radius);                              虽是父类,但他也有父类的,他里面也有一条隐式的父
       }                                                                                                         类构造函数,用来给自己初始化。他的父类则是Object
       public B(){                                                                                          然而在次之前,还没有int   radius=10;而是默认值0
            super();          //这里调用了Object的构造函数                               所以结果会是那样。
             System.out.println("B constructor");
              draw();这里为什么调用的是子类的draw()而不是父类的?
        }
}
public class A extends B{
        private int radius = 1;
        public void draw(){
            System.out.println("A.draw(),radius = "+radius);
        }
        
        public A(int radius){
            super();         //这里调用了B类的构造函数
            this.radius = radius;
            System.out.println("A contructor");
        }
        public static void main (String[] args){
                A a = new A(5);
        }
}





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2