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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 柏涛 中级黑马   /  2013-12-28 16:26  /  1558 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

class Super{
int i=10;
Super(){
  
  print();
  i=20;
}
  void print() {
  
   System.out.println(i);
   
}

}

public class Sub extends Super {
int j=30;
Sub(){
  print();
  j=40;
  
}


  void print() {
  
   System.out.println(j);
   
}

public static void main(String[] args) {
  
  System.out.println(new Sub().j);
  
}
}
为什么输出结果是03040?求详解。。

评分

参与人数 1技术分 +1 收起 理由
乔兵 + 1

查看全部评分

6 个回复

倒序浏览
{:soso__3669389859068460655_3:}
0不知道
回复 使用道具 举报
/**
* 子类对象的实例化过程,6步:
* 1.分配成员变量的存储空间并进行默认的初始化,就是用new关键字产生对象后,对类中的成员变量进行初始化赋值。
*   成员初始化顺序:静态成员-->代码块-->非static成员
* 2.绑定构造方法参数,就是将构造方法所传递进来的实参赋值给构造方法中的形参变量
* 3.如有this语句调用,则调用相应的重载构造方法,回到步骤2开始执行,被调用方法执行完毕后,回到当前构造方法,
*   当前构造方法则直接跳转到步骤6执行
* 4.显式或隐式追溯调用父类的构造方法(一直到Object类为止),父类的构造方法又从步骤2开始对父类执行这些
*   流程,父类的构造方法执行完毕后,回到当前构造方法继续往下执行。
* 5.进行实例变量的显示初始化操作,也即是执行在定义成员变量时就对其赋值的语句。
* 6.执行当前构造方法中的方法体中的程序代码
*/

按照以上初始化步骤,你就可以理解为什么输出结果是03040了,当你在实例化子类时,第一步对子类中的变量默认初始化,然后没有参数列表,所以跳过第2步,进行隐式默认的super()父类初始化,父类中此时变量都是默认初始化,打印为0,回到子类中继续执行,对子类变量进行显示初始化,此时为30,然后开始执行方法体,打印为30,再将40赋值给j。回到main函数继续执行,打印出现在的J值为40,所以最后结果为03040

评分

参与人数 1技术分 +1 收起 理由
乔兵 + 1

查看全部评分

回复 使用道具 举报
大概是这样。
  1. System.out.println(new Sub().j);
复制代码

首先要调用父类的构造方法。父类是不包含int类型的j的。所以初始化为0.父类的print打印出0.
然后,是之类的构造方法,这里就有j了,还是有值的:
  1. int j=30;
  2. Sub(){
  3.   print();
  4.   j=40;
  5.   
  6. }
复制代码

同时,这个方法里,为新实例附了值,40.
然后:
  1. System.out.println(new Sub().j);
复制代码
打印出40.
我也只是猜测……好无聊啊,这种题,想问问,哪里考的?

评分

参与人数 1技术分 +1 收起 理由
乔兵 + 1

查看全部评分

回复 使用道具 举报
上面解释错了,我代码试了下,有问题,等下说啊,我在调试下看,不好意思。
回复 使用道具 举报
/**
*打印结果为: Sub0        Sub30        40
*初始化顺序没错,只是父类在初始化时调用的是子类中复写的print方法,此时i值为默认初始化的0,
*父类构造方法完毕后回到子类构造方法,对i进行显示初始化30,然后执行方法体调用print方法,为30,
*继续执行赋值40,回到主函数执行打印40,所以最后顺序03040是这么得来的。
*/

public class test {
        public static void main(String[] args){
                System.out.println(new Sub().i);
        }
}

class Super{
        int i = 10;
        String str = "hell";
        Super(){
                print();
                i = 20;
        }
        void print(){
                System.out.println("super"+i+str+"yes");
        }
}

class Sub extends Super{
        int i = 30;
        String str = "hell";
        Sub(){
                print();
                i = 40;
        }
       
        void print(){
                System.out.println("Sub"+i);
        }
}
回复 使用道具 举报
doitforyou 发表于 2013-12-28 17:14
/**
*打印结果为: Sub0        Sub30        40
*初始化顺序没错,只是父类在初始化时调用的是子类中复写的print方法, ...

解释错了,不好意思,又误人子弟了。第一次默认初始化时父类构造方法里也执行了一次print方法,代码显示是子类中的print方法,但是父类中是无法调用子类的方法的,这一点解释错了,具体原因我也不太懂,有点懵了,惭愧,等我明白了再告诉你。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马