关于继承的变量赋值、覆盖,构造函数的问题,坐等解答

yh0123123 2012-10-23 09:52:21
是论坛有朋友发过的一个问题。
class A{
String str="A";
A(){
init();
}
public void init(){
System.out.println(str);
}
}
class B extends A{
String str="B";
B(){
super();
}
public void init(){
System.out.println(str);
}
}

public static void main(String[] args){
A b=new B();
System.out.println(b.str);
}

答案应该是
null
A 本来觉得自己是懂了,但是试着把class B中的 String str="B";去掉,打印结果变成了

A
A 这里感觉比较迷茫,第一次的打印有null我觉得是b的构造是调用父类class A的构造,父类调用的init函数因为子类有重写,我觉得应该是调的B类的init,此时子类还未完成构造,所以子类的str还未赋值。但是init调用实在父类的构造函数里的,此时父类应该也还未完成构造,但是为什么子类中去掉String str="B";后调用init就可以打印出A了?此时父类中的str已经赋值了吗?比较困惑,求高手能帮我解答下,也就是构造函数和变量赋值的顺序问题。感觉语言组织的不适太好,希望大家能懂。还有突然发现没分了很不好意思,但是现在又特纠结这问题,厚着脸皮发了,望能解答,谢谢!
...全文
179 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
yh0123123 2012-10-24
  • 打赏
  • 举报
回复
有点明白了。这是不是构造函数的调用有个类似回溯的过程,先从子类到父类,先给变量赋默认值,然后从父类回溯,每次执行父类构造函数时先给变量赋自定义的值,父类构造函数结束再到子类,子类构造函数执行前也是先给变量赋自定值
nmyangym 2012-10-24
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]
有点明白了。这是不是构造函数的调用有个类似回溯的过程,先从子类到父类,先给变量赋默认值,然后从父类回溯,每次执行父类构造函数时先给变量赋自定义的值,父类构造函数结束再到子类,子类构造函数执行前也是先给变量赋自定值
[/Quote]
是这样的.
参考一下:
http://wenwen.soso.com/z/q191435823.htm
yh0123123 2012-10-24
  • 打赏
  • 举报
回复
嗯弄明白了,谢谢各位了
huntor 2012-10-24
  • 打赏
  • 举报
回复
不要在构造方法里调用可被override的方法
  • 打赏
  • 举报
回复
public static void main(String[] args){
A b=new B();
System.out.println(b.str);
}
执行A b=new B();然后调用B的构造函数,但是由于B继承自A,所以在调用B的构造函数之前先调用父类A的构造函数,在调用A的构造函数前,A类会先对他的字段进行初始化,即先执行String str="A";
A(){
init();
}
然后执行init();这里的init()方法是B里的init()方法,因为B的init()覆盖了父类A的();
public void init(){
System.out.println(str);
}
然后输出str,因为你在B中声明的变量str覆盖了A中的str,这个时候A类的构造函数调用还未结束,故B的字段str还未被初始化,默认值为null,b是A的对象,所以b.str为"A";此时输出结果为null A。
当你删掉String str="B"后,System.out.println(str)中的str就变成继承自A的变量了,由于在调用A的构造函数前A就对str进行了初始化,故会输出"A",b.str="A",故输出结果为A A。
同类问题请看看这个帖子http://topic.csdn.net/u/20121024/00/7fc7aab8-d9cd-4fff-aede-61b270cb5ade.html?82921
躺平摆烂 2012-10-23
  • 打赏
  • 举报
回复
当调用B的构造方法时,有如下顺序:B()=> A() => A的str赋值 => B 的init()=> 输出B的str(还没赋值)=> B的str赋值。
如果去掉String str='B',则有如下顺序::B() => A() => A的str赋值 => B 的init()=> 输出A的str( 已经赋值)
躺平摆烂 2012-10-23
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]

引用 1 楼 nmyangym 的回复:
(在一个类里)构造函数执行前是先给成员变量显式赋值的. 你去掉了子类的 String str='B';那输出的是父类的str,此时已经赋值'A'了。

那为什么不去掉String str='B'的时候会输出null呢??既然构造前就赋值了那不管是调用父类的init还是子类重写的init不是都可以输出str值吗??
[/Quote]
因为如果子类b没有str的话,那b的str就是父类的str了.当调用
yh0123123 2012-10-23
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 nmyangym 的回复:]
(在一个类里)构造函数执行前是先给成员变量显式赋值的. 你去掉了子类的 String str='B';那输出的是父类的str,此时已经赋值'A'了。
[/Quote]
那为什么不去掉String str='B'的时候会输出null呢??既然构造前就赋值了那不管是调用父类的init还是子类重写的init不是都可以输出str值吗??
nmyangym 2012-10-23
  • 打赏
  • 举报
回复
(在一个类里)构造函数执行前是先给成员变量显式赋值的. 你去掉了子类的 String str='B';那输出的是父类的str,此时已经赋值'A'了。

62,615

社区成员

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

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