【一个关于类初始化顺序的问题】能帮我解释一下这段程序的运行结果吗?

woodytid 2008-06-01 06:40:33
加精
class A {
String name = isName();

String isName() {
System.out.println("222222222");
return null;
}

A() {
System.out.println("333333333");
}
}

class B extends A {
String name = isName();

String isName() {
super.isName();
System.out.println("1111111111");
return "aa";
}
}

class Demo {
public static void main(String[] args) {
A b = new B();
}
}


结果

222222222
1111111111
333333333
222222222
1111111111

为什么初始化父类name的时候调用的是子类重写之后的方法?
...全文
1938 135 打赏 收藏 转发到动态 举报
写回复
用AI写文章
135 条回复
切换为时间正序
请发表友善的回复…
发表回复
lzycsd 2008-09-11
  • 打赏
  • 举报
回复
mark
zy353748272 2008-08-19
  • 打赏
  • 举报
回复
class A {
String name = isName();

String isName() {
System.out.println("A.isNme()!");
return null;
}

A() {
System.out.println("A's constructor!");
}
}

class B extends A {
String name = isName();

String isName() {
System.out.println("B.isName() is called!");
super.isName();
System.out.println("B.isName()!");
return "aa";
}
}

public class Demo {
public static void main(String[] args) {
A b = new B();
}
}
/*output:
B.isName() is called!
A.isNme()!
B.isName()!
A's constructor!
B.isName() is called!
A.isNme()!
B.isName()!
*/
A a = new B();
1,执行A中字段name的初始化,从而调用B的isName方法首先输出B.isName() is called!
2,然后执行super.isName() 输出A.isNme()!
3,执行System.out.println("B.isName()!"); 输出B.isName()!
4,调用A的构造器输出A's constructor!
5,执行B的字段name的初始化调用B的isName输出B.isName() is called! 在此方法里又调用A的isName方法(super.isName)输出A.isNme()!然后输出B.isName()!
qijiacj 2008-08-08
  • 打赏
  • 举报
回复
学习
jerry320 2008-08-06
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 lsxfhao 的回复:]


1.先执行A的field
发现isName()被重写。
调用B的isName()。

2.执行A的构造方法。

3.执行B的field
调用B的isName()
[/Quote]
碑文 2008-07-29
  • 打赏
  • 举报
回复
[Quote=引用 124 楼 woodytid 的回复:]
引用 91 楼 shou2 的回复:
反问楼主一个问题啊,先看代码

class A {
String name = isName();

private String isName() {
System.out.println("222222222");
return null;
}

A() {
System.out.println("333333333");
System.out.println("this是"+this.getClass()+"类型的对象");
this.isName();
}
}
class B extends A {
String name = isName();

St…

由于我是学了java没多久,自己的理解是,父类的private isName方法跟子类的isName方法根本就是2个方法,一个存在父类中,一个在子类中,当你用子类的对象调用的应该是子类的方法吧?问题是父类中根本没有子类的isName方法,那怎么能调用的了?你可以将子类的isName方法改个名字,在父类里面用this调用看看,会提示找不到方法.至于为什么会调用了父类的isName,我只能将它理解为java自身的特性而尔,在语法上this.isName()并没有问题,因为就算父类没有子类那个isName方法它本身也有一个isName()方法,在父类的方法里面用this调用本身的方法是可以的吧?只是this是多余的,写不写也没多大影响.在基于父类里面用了子类对象this来调用父类里面没有的子类方法的情况下,java把this.isName()看成是调用父类本身的isName方法来避免出现错误这是有可能的.当然,这只是我的想法,说不定深入了解java的人会有一个更加容易懂得的解释.但是如果java会这样去做的话,本身就是一件很有趣的事情.我们不是java,了解java的想法就像了解另外一个人的想法一样,并不能很简单明白是为什么,但是将探讨java看成探讨一个人,那么会发现一切都是那么的神奇.(突然有感,不好意思)
[/Quote]
持续关注这个问题,第一次看完了这么长的一帖子
觉得受益匪浅,又加强和巩固了一下初始化方面的知识
同时对于大家学习方法有了新的认识
不停的尝试,就在尝试的出错和改错中间不断进步。
chendabian 2008-07-23
  • 打赏
  • 举报
回复
A b = new B();

这个跟B b =new B();似乎没有区别~~ 结果一样
lemu_bsh 2008-07-22
  • 打赏
  • 举报
回复
=========================================
我理解的哈:

1.进入B构造函数,B继承A,构造A部分

2.进入A构造函数
3.A构造函数中,初始化A成员变量
4.A构造函数中,运行A构造函数本身
5.退出A构造函数

6.构造B部分
7.B构造函数中,初始化B成员变量
8.B构造函数中,运行B构造函数本身

9.退出B构造函数
===========================================
Eric_Ma_Java 2008-06-28
  • 打赏
  • 举报
回复
17L的应该是正解!
chendabian 2008-06-26
  • 打赏
  • 举报
回复
有空 再细细研究
xian_hf 2008-06-07
  • 打赏
  • 举报
回复
回20楼,有继承关系的是先父后子
我不是大明 2008-06-06
  • 打赏
  • 举报
回复
楼主问的是:

为什么初始化父类name的时候调用的是子类重写之后的方法?

而楼上很多人给楼主解决一堆多态,我想这点楼主也非常清楚。
我个人猜想,楼主可能是从C++程序员转过来的JAVA程序员
这个是C++和JAVA的处理上的不同。

对于C++语言:在构造函数中 A调用 isName 是不会调用到 B 中的函数的;
这样做我个人认为不好,我认可JAVA 这种做法,简单让人容易理解。
woodytid 2008-06-06
  • 打赏
  • 举报
回复
[Quote=引用 91 楼 shou2 的回复:]
反问楼主一个问题啊,先看代码

class A {
String name = isName();

private String isName() {
System.out.println("222222222");
return null;
}

A() {
System.out.println("333333333");
System.out.println("this是"+this.getClass()+"类型的对象");
this.isName();
}
}
class B extends A {
String name = isName();

String isName() {
//su…
[/Quote]

由于我是学了java没多久,自己的理解是,父类的private isName方法跟子类的isName方法根本就是2个方法,一个存在父类中,一个在子类中,当你用子类的对象调用的应该是子类的方法吧?问题是父类中根本没有子类的isName方法,那怎么能调用的了?你可以将子类的isName方法改个名字,在父类里面用this调用看看,会提示找不到方法.至于为什么会调用了父类的isName,我只能将它理解为java自身的特性而尔,在语法上this.isName()并没有问题,因为就算父类没有子类那个isName方法它本身也有一个isName()方法,在父类的方法里面用this调用本身的方法是可以的吧?只是this是多余的,写不写也没多大影响.在基于父类里面用了子类对象this来调用父类里面没有的子类方法的情况下,java把this.isName()看成是调用父类本身的isName方法来避免出现错误这是有可能的.当然,这只是我的想法,说不定深入了解java的人会有一个更加容易懂得的解释.但是如果java会这样去做的话,本身就是一件很有趣的事情.我们不是java,了解java的想法就像了解另外一个人的想法一样,并不能很简单明白是为什么,但是将探讨java看成探讨一个人,那么会发现一切都是那么的神奇.(突然有感,不好意思)
apples_009 2008-06-06
  • 打赏
  • 举报
回复
当然如果有静态方法块或静态变量会先执行..
apples_009 2008-06-06
  • 打赏
  • 举报
回复
先从上到下(先父类再一步步下来)为变量分配内存.再构造方法/不用搞得哪么乱..

每一次看这个贴从上看下来都会头晕..呵呵..定力不够.
woodytid 2008-06-06
  • 打赏
  • 举报
回复
[Quote=引用 91 楼 shou2 的回复:]
反问楼主一个问题啊,先看代码

class A {
String name = isName();

private String isName() {
System.out.println("222222222");
return null;
}

A() {
System.out.println("333333333");
System.out.println("this是"+this.getClass()+"类型的对象");
this.isName();
}
}
class B extends A {
String name = isName();

String isName() {
//su…
[/Quote]

不解!求解!!
CRC622 2008-06-06
  • 打赏
  • 举报
回复
学习中,还不太懂
yongpang 2008-06-06
  • 打赏
  • 举报
回复
我也同意楼上的分析
macongbin88 2008-06-05
  • 打赏
  • 举报
回复
mark and study
liu78778 2008-06-05
  • 打赏
  • 举报
回复
关键在于
在你调用构造方法去构造对象的时候
它会先判断该类是否有父类 如果有 它会直接调用父类的构造方法
这样一层一层的调用 就到了基类(也就是Object类)
然后它开始构造所有该类的属性 从基类的属性开始(在内存中分配内存空间)
构造完属性 就执行构造方法中的代码来初始化构造好的属性(如果没有显式给属性初始化,系统就自动初始化属性)
当基类的所有属性都构造并且初始化完毕 程序流程就指向其下一级父类
这样一层一层的构造和初始化 直到把该类所有的属性都构造和初始化完毕
这个对象就构造完毕了

以上是我的观察和理解 如有肤浅之处,请大家指正 不胜感激
liu78778 2008-06-05
  • 打赏
  • 举报
回复
程序执行步骤如下:
程序开始运行,找到了main()方法,执行 A b = new B();
这时候 调用了B类的默认构造方法 来构造B类的对象
发现B类是继承自A类
于是
直接先调用了A类的构造方法 来初始化B类中继承自A类的属性
执行到了 A类中的 String name = isName();
由于构造的是B类的对象 所以这里调用的是B类中重写了的isName()方法
B类中的isName()方法的第一句super.isName(); 又调用了A类的isName()方法
于是先执行了A类的isName()方法 输出了222222222
然后继续回到B类的isName()方法 输出了1111111111
然后就初始化完毕B类继承自A类的name属性
执行A类的构造方法中的其他语句 输出了333333333
现在开始初始化B类自己的name属性
同样调用了本身的isName()方法 通过super调用了A类的isName()
输出了后面的两句

这流程是有点乱
加载更多回复(110)

62,616

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧