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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

class Base{
private int i=2;
public Base(){
  this.display();
}
public void display(){
  System.out.println("the Base function i="+i);
}
}
class Derived extends Base{
private int i=22;
public Derived(){
  i=222;
}
public void display(){
  System.out.println("the Derived function i="+i);
}
}

public class test1 {
public static void main(String[] args) {
  new Derived();
}
}


评分

参与人数 1技术分 +1 收起 理由
黄奕豪 + 1 鼓励一下!

查看全部评分

6 个回复

倒序浏览
本帖最后由 罗文杰 于 2012-6-5 12:38 编辑

个人总结的对象初始化步骤(无静态和构造代码块):
1.设置成员的值为默认的初始值(0,false,null)。
2.调用对象的构造方法(但是还没有执行构造方法体)。
3.调用父类的构造方法。
4.使用初始化程序和初始块初始化成员。
5.执行构造方法体。

当你执行new Derived();的时候 先把的值设置成了默认值0,然后去调用了父类的构造方法,由于display()方法子类复写过,所以调用父类构造方法时用子类的 display()方法,这时候打印结果就是the Derived function i=0;调用完父类的构造方法后,初始化i的值为22,然后执行子类方法体,把i赋值为222。
如果你在子类的构造函数里第一句加上输出i的值,
public Derived(){
  System.out.println(i);
  i=222;
}
你会发现这个时候会输出:
Derived function i=0
22

评分

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

查看全部评分

回复 使用道具 举报
罗文杰 发表于 2012-6-5 12:37
个人总结的对象初始化步骤(无静态和构造代码块):
1.设置成员的值为默认的初始值(0,false,null)。
2. ...

请问:为什么会把值设置成默认值0 ??  不是已经private int i = 22; 初始化过了吗?
回复 使用道具 举报
本帖最后由 李天甲 于 2012-6-5 12:58 编辑

简单调试了以下,请看代码中的注释
  1. class Base{
  2.     private int i=2;        //步骤4 然后再初始化父类的成员变量
  3.     public Base(){          //步骤3 开始执行父类的构造函数,先开始构造父类
  4.         this.display();     //步骤5 问题可能出在这里 父类的构造函数中调用子类的方法,转而执行子类的方法.
  5.                              // 这时候,父类中的私有变量 i 是已经定义的,而子类的还没有初始化
  6.     }
  7.     public void display(){
  8.         System.out.println("the Base function i="+i);
  9.     }
  10. }
  11. class Derived extends Base{
  12.     private int i=22;
  13.     public Derived(){        //步骤2 执行子类的构造函数 但是由于子类隐含了父类的构造函数,所以转而执行父类构造函数
  14.         i=222;
  15.     }
  16.     public void display(){  //步骤6 父类调用子类的方法
  17.         System.out.println("the Derived function i="+i);        //最后输出7 嘿嘿,当然子类成员变量 i 还没有赋值呢.....
  18.     }
  19. }

  20. public class test1 {
  21.     public static void main(String[] args) {
  22.         new Derived();     //步骤1 开始new对象
  23.     }
  24. }
复制代码

评分

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

查看全部评分

回复 使用道具 举报
从main方法开始,执行new Derived()时,调用Derived的构造方法,因为继承Base类,默认Derived构造方法第一句有:super();,继而调用Base的构造方法,
Base调用自己的display函数,因为被Derived重写,然后执行Derived的display方法,因为这时 i 还没有被赋值,所以默认是0。
故打印出“the Derived function i = 0 ”.
回复 使用道具 举报
class Base{
private int i=2;
public Base(){
   this.display();
}
public void display(){
   System.out.println("the Base function i="+i);
}
}
class Derived extends Base{
private int i=22;
public Derived(){
   i=3;
}
public void display(){
  System.out.println("the Derived function i="+i);
}
}

public class test1 {
public static void main(String[] args) {
   new Derived();//调用改代码时 首先调用父类的构造函数 将调用父类中的display()函数 而子类中继承了该方法 并实现了复写  若子类没有复写该方法则可以正常打印
}
}
回复 使用道具 举报
  1. class Base{
  2. private int i=2;///(2)由于父类和子类中都没有静态的变量和方法,所以new Derived() 执行之后直接到这句,父类的成员变量定义值初始化。
  3. public Base(){
  4.   this.display();  ///(3)接着,构造代码块初始化之后,进入构造方法,这里调用了被复写的display(),所以执行子类的display()
  5. }
  6. public void display(){
  7.   System.out.println("the Base function i="+i);
  8. }
  9. }
  10. class Derived extends Base{
  11. //private static int i=22; ///如果定义为静态的,则在父类构造方法初始化时调用display()之前,i已经初始化为定义值22。结果为22.
  12. private int i=22;
  13. public Derived(){
  14.   i=222;
  15. }
  16. public void display(){
  17.   System.out.println("the Derived function i="+i); ///(4)由于父类被private修饰的非静态成员变量不会子类覆盖,所以这里的i是子类中定义的。
  18.                                                                                                 ///由于此时还没有来得及定义值的初始化,所以i是默认值0。
  19. }
  20. }

  21. public class Test1 {
  22. public static void main(String[] args) {
  23.   //new Derived();//(1)
  24.   new Base(); ///Base类的构造方法中调用谁的display()是在这儿确定的,如果改为这样,则调用的是父类的display,结果为2.。
  25. }
  26. }
复制代码
出现打印的int类型变量值为0,往往是由于该变量还未来得及定义值的初始化引起的,其所指向的存储区域中为默认值0。成员变量的默认值初始化是在类装载阶段完成的,具体请查阅相关资料。虽然是个小练习,但我建议楼主注意类名的命名规范,以养成良好的编码习惯。

评分

参与人数 1技术分 +1 收起 理由
袁錦泰 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马