大家来讨论构造方法问题

seesea10523 2006-08-30 05:41:52
我贴出一段代码
public class Target extends Depend {

int i = 30 ;

public Target() {
print();
i = 40 ;

}
void print() {

System.out.println( " Target=> " + i);

}

public static void main(String[] args) {

System.out.println(new Target().i);

}

}

class Depend {

int i = 10 ;
public Depend() {

print();
i = 20 ;
}
void print() {

System.out.println( " Depend=> " + i);
}

}

运行结果是:
Target=> 0
Target=> 30
40
大家讨论 为什么会这样
...全文
418 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
lsslu 2006-09-01
  • 打赏
  • 举报
回复
System.out.println(new Target().i);
这句就是输出i的值的吧,所以会输出40。其他的print()方法输出的。
seesea10523 2006-09-01
  • 打赏
  • 举报
回复
呵呵 谢谢各位高手讨论
总结的也差不多了
受益匪浅啊 哈哈
可惜分不够
但是也要结帖啊
hyc_hover 2006-08-31
  • 打赏
  • 举报
回复
mark
maquan 2006-08-31
  • 打赏
  • 举报
回复
TO jackra(永恒の金条):

“成员变量没有 override”这个结论是没错的。

你试试下面这段代码,打印出来的东西是不一样的,也就是说,通过不同的类型访问同一个对象的同名成员变量,实际访问的是两个不同的变量:

Target t = new Target();
Depend d = (Depend)t;
System.out.println("t: " + t.i);
System.out.println("d: " + d.i);
seesea10523 2006-08-31
  • 打赏
  • 举报
回复
又有新疑问:
如果我把int i = 30 ;这句注释掉 也就是没有成员变量的重载
这时所有用到的都是父类Depend的成员变量i
这时结果是:
Target=> 10
Target=> 20
40
按照10楼和11楼的说法就解释不通了。
类实例化的时候是先初始化成员变量再调用构造方法。
越来越糊涂了。
哪位大虾 给正解
jackra 2006-08-31
  • 打赏
  • 举报
回复
楼上说
3. 子类与父类中同名的成员变量,是两个独立的变量。在父类中为成员变量赋值,不会影响子类中的同名变量。也就是说,成员变量没有 override。

有点疑义.在下认为理解为:i指定的是target中的i而非depend中的i.

target的print()换成如下.看结果可知.
System.out.println( " Target=> " + i);

System.out.println( " Target super=> " + super.i);
看看?

对子而言,有this与super之分.对外而言,无this与super之分.i依然被重载.
sucfre 2006-08-31
  • 打赏
  • 举报
回复
构造方法的执行顺序是这样的:
1.在对象的构造函数执行之前会先执行其父类的初始化.
2.如果父类还有父类的话依次递归
3.始化的过程是首先定义变量,如果没有初始化变量就赋一个默认值.
上述问题是这样的当你在父的构造函数里调用的print其实是重载后的.是子类的方法.但这个时候i并没有定义(这个可以确定,不信自己可以有debug跟一下).不知道java为什么会输出0,也许是java的bug .当在子类的构造函数中调用print方法时,此时i 已定义.
建议:构造函数只是初始化工作.不要在里面执行方法(用于初始化的方法除外),这是写程序的大忌.
maquan 2006-08-31
  • 打赏
  • 举报
回复
这的确是一个 fancy 的问题,我单步调试了好几遍,终于弄清楚了 :)

我想,有 3 个关键点,搞清楚就好办了:

1. 类实例化的时候,所有成员变量都有缺省值,int 型变量的缺省值为 0;

2. 成员变量赋初值的操作是先于构造方法而执行的;

3. 子类与父类中同名的成员变量,是两个独立的变量。在父类中为成员变量赋值,不会影响子类中的同名变量。也就是说,成员变量没有 override。

所以,Target 构造的时候,先调用 Depend 的构造,后者调用的 print() 实际是 Target 中的 print(),打印出来的是 Target 中的 i,而这个 i 还没有赋值,所以打印出 0。
inorro 2006-08-31
  • 打赏
  • 举报
回复
首先调用父类无参的构造方法,这时的i都初始化是0。Target.i=0,Depend.i=0 然后Depend构造方法中有print(),但此时调用的确是Target中的print(),因为这时print()方法被重载了,又因为这时的Target.i的值还是0(Target.i=30还没有执行,只是Depend.i=10执行了),而Depend.i=10,所以输出Target=> 0,此后大家都明白吧,在这就不说了。
seesea10523 2006-08-31
  • 打赏
  • 举报
回复
首先调用父类无参的构造方法这点我知道,可是为什么i值为0并且为什么父类调用的是子类的重载方法呢?各位大虾给个详解。
bigc2000 2006-08-31
  • 打赏
  • 举报
回复
晕,没有看到主程序的print,不好意思,我总结下

1. 设置成员的值为缺省的初始值 (0, false, null)
2. 调用对象的构造函数 (但是还没有执行构造方法体)
3. 调用父类的构造函数,如果父类的构造函数调用了其他函数,则
须注意,如果该函数被子类重载,那么实际调用的是子类的相应函数,如果该函数没有重载,那么父类调用该函数。如果该函数使用了成语变量,那么需要先检查成员变量是否要赋值 ,(调用赋值 如i=30)
4. 使用初始化程序和初始块初始化成员(调用赋值 如i=30)
5. 执行构造方法体

问题是第3步与第4步发生的。
inorro 2006-08-31
  • 打赏
  • 举报
回复
又有新疑问:
如果我把int i = 30 ;这句注释掉 也就是没有成员变量的重载
这时所有用到的都是父类Depend的成员变量i
这时结果是:
Target=> 10
Target=> 20
40
按照10楼和11楼的说法就解释不通了。
类实例化的时候是先初始化成员变量再调用构造方法。
越来越糊涂了。
哪位大虾 给正解



这个疑问很简单,int i = 30 ;这句注释掉也就是说Target中没有i这个变量,也就不可能初始化值,语句System.out.println( " Target=> " + i);只能上父类找这个i值,这是父类的i值是10,所以输出Target=> 10,因此10楼和11楼的说法是对的。
bigc2000 2006-08-31
  • 打赏
  • 举报
回复
没有明白,为什么输出40!虽然i=40,但是没有print语句呀。
还有继承类本来就是保存一个父类的索引而言。,重写方法,也只是类似于C++的虚函数。
bigc2000 2006-08-31
  • 打赏
  • 举报
回复
忘了,以前见过有人专门写的一篇文章说明。
实际上是 int i= 30 ,这个赋值,与构造函数的问题。
大致是这样的

子类构造函数 如果没有显示调用父类的构造方法,会缺省的去掉用父类的不带参数的构造函数
Target()所以会调用Depend(),由于Depend()他有调用Print(),print被重新写过了
所以会调用子类的Print,此时子类的i并没有赋值,而是初始值0,父类调用完print后,返回到子类构造函数,子类继续调用Print,Print发现i没有初始化(注意这是类初始化后发现的),因此,调用赋值i=30,然后就打印出30,并且i=40 了,

这应该就是
Target=> 0
Target=> 30

至于最后的40 ,我没有明白。

Layman_Farmer 2006-08-31
  • 打赏
  • 举报
回复
题目很好,就是还没有大虾搞定
sos110 2006-08-30
  • 打赏
  • 举报
回复
========================================================================
java技术交流,讨论java的技术细节和最新技术。欢迎中高级程序员加入讨论。QQ群:3001581(人员有限,不接收初学者,谅解)
zhenshifeijin 2006-08-30
  • 打赏
  • 举报
回复
那个i在什么时候被第一次赋值啊?
gefengxztg 2006-08-30
  • 打赏
  • 举报
回复
其实java并不是要等父类构造完了在构造子类的
子类方法覆盖父的方法,
在构造方法里面最好只做初始化的工作
不要调用方法
jackra 2006-08-30
  • 打赏
  • 举报
回复
Target=> 0
这个挺头晕.
算是自动初始化的值?
刚开辟过空间,自动初始化为0?
那个达人可以帮忙解释一下?
DrinkT 2006-08-30
  • 打赏
  • 举报
回复
首先调用父类无参的构造方法,super()是隐藏的,但是一定会执行
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
public class Target extends Depend {
int i = 30 ;
public Target() {
//super();---------首先调用父类的构造方法
print();
i = 40 ;
}
void print() {
System.out.println( " Target=> " + i);
}
public static void main(String[] args) {
System.out.println(new Target().i);
}
}
class Depend {
int i = 10 ;
public Depend() {
print();
i = 20 ;
}
void print() {
System.out.println( " Depend=> " + i);
}
}
加载更多回复(2)

62,615

社区成员

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

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