A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 李宁 中级黑马   /  2013-1-21 18:02  /  1943 人查看  /  12 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 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
在网上看到的一个题,不明白为什么输出的是这个

评分

参与人数 1技术分 +1 收起 理由
Rancho_Gump + 1 赞一个!

查看全部评分

12 个回复

倒序浏览
A a = new A(5);
开了A的空间
首先没指定 调用哪个构造函数,直接默认调父类无参构造。
然后又传一个5进去,调用int radius这个构造 ,把值给指向了5
输出一句里面的A contructor
回复 使用道具 举报
本帖最后由 柴乔军 于 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方法,是因为你创建的是一个子类对象,而子类中又重写了父类的方法,所以调用的自然就是子类的方法

评分

参与人数 1技术分 +1 收起 理由
Rancho_Gump + 1 赞一个!

查看全部评分

回复 使用道具 举报
这种题。。。太隔了。。。
回复 使用道具 举报
代码执行顺序是这样的 ,  首先A继承B, B是父类, 通常情况下 子类被调用, 父类的构造函数一定会先执行..  所以先执行的是Public B方法  然后 B方法里有个draw();  draw方法被子类重写, 根据概念, 重写一定调用子类, 所以是 子类的draw, 但是, 这时候我们还没有真正跳出父类的构造函数, 因为draw的方法还没执行完..  所以 这时候 int radius 是个空值, 默认 int 空值就是0,  然后打印出0后 跳出父类的构造函数.. 接着 执行子类的方法..  传进去一个5 打印出最后一个...  这道题 重点就是 父类里的子类方法..  执行的时候 由于是在父类的构造方法里, 子类方法没有被真正意义上的调用.. 所以 子类里的值没有传进去.. 多看点书吧.. 书上都有写呢

评分

参与人数 1黑马币 +9 收起 理由
Rancho_Gump + 9 赞一个!

查看全部评分

回复 使用道具 举报
再说白点.. 这个int 并没有被初始化.. 懂了没? 方法没跳出 没有被初始化.. 所以 int 默认 为0
回复 使用道具 举报
苏克 中级黑马 2013-1-21 19:09:28
7#
这种题要顺着一步一步往上捣才行。
回复 使用道具 举报
我终于想通了,从某个方面来说,这题是有一点嗝
  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. }
复制代码
面性对象的基础要打好啊

评分

参与人数 1技术分 +1 收起 理由
Rancho_Gump + 1 很给力!

查看全部评分

回复 使用道具 举报
李宁 中级黑马 2013-1-21 19:50:01
9#
我以为draw()方法在父类的构造方法里面就调用父类,看来是错了
回复 使用道具 举报
已经被重写的方法,调用的当然是重写后的方法了
回复 使用道具 举报
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的对象
        }
}
回复 使用道具 举报
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();//这里执行完后虚拟机就返回刚才的标记那里继续执行

     
回复 使用道具 举报
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);
        }
}
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马