java问题求高手解答!!

abstractclassA3{publicabstractvoidprint();A3(){print();}classB3extendsA3{privateinti=... abstract class A3{
public abstract void print();
A3(){ print();}

class B3 extends A3{
private int i=2;
public void print(){
System.out.println("i= "+this.i);}

public class Test314 {
public static void main(String[] args){
B3 r=new B3();

这段程序的打印结果是i=0,为什么?求高人详解!谢谢啦!!
System.out.println("i= "+this.i);} 和 System.out.println("i= "+i);}的打印结果一样。怎么回事?求解答。谢谢啦!

print()会去执行B3的print(),但是这时,i还未负值,只是初始化完毕。这里不是已经给i赋值=2来完成初始化了的吗?那为什么会是=0?
展开
 我来答
财神万岁86
2010-08-06 · TA获得超过1.1万个赞
知道小有建树答主
回答量:898
采纳率:0%
帮助的人:485万
展开全部
这个是一个继承的问题,自己写代码尽量不要这么写,容易引起混乱。
先说明一点问题,B3 r=new B3();B3无参构造函数默认首先执行父类的无参构造函数;并且,没有执行完毕前,B3中的全部属性只是初始化状态,比如说:int类型的都是0,String的都是NULL。
看看它的执行顺序,new B3()时,会跳转到A3的A3(){ print();},需要注意的是,print()会去执行B3的print(),但是这时,i还未负值,只是初始化完毕,所以,值为0.
由于B3整个执行顺序只有i,所以,this.i(当前类的i)和i是一回事。
加断点,可以看到执行顺序。

是这样,当A3执行 print()时,i还没有被负值,因为new B3()还没有结束,一个类还没有实例,那么,这个类中的属性没有被负值,所以,i只是等于0.
加3个断点看看,A3()一个、new B3()一个、B3的print()中一个。
q278541473
2010-08-05 · TA获得超过118个赞
知道答主
回答量:35
采纳率:0%
帮助的人:0
展开全部
class B3 extends A3
你先把extends A3去掉,再试试。是不是没任何东西输出。
这说明,真正调用print方法的不是B3方法,而是A3的构造函数里面调用的
print方法,那时候i的初始化值是0。
public static void main(String[] args){
B3 r=new B3();
r.print(); //这样输出的才是2,调用print的是B3
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
resong27lhk
2010-08-09 · TA获得超过157个赞
知道答主
回答量:42
采纳率:0%
帮助的人:69万
展开全部
事实上,上面的都说的是表面现象,实质上并非如此。

参看《Thinking in JAVA》(第四版)的第七章——复用类——7.2.1 初始化基类 的相关文字,你就会发现在继承(抽象类的继承是一种实现)的时候,有自己的初始化顺序和隐式初始化,这个才是你这个问题的实质。

具体来说,是这样的:
首先,看初始化的顺序。
大家都知道,初始化的顺序就是四部:
静态属性——非静态属性——构造器——调用的方法
这里,貌似还是得不到答案,按照这个来说,那个i还是应该等于2。可是这里有个一初始化陷阱,就是下面的第二步。
然后,看继承或者实现抽象类的引用初始化。
每一个抽象类被实现或者某个类被继承时,他的子类都会隐式的含有一个父类属性,这个属性的引用就是大家熟知的“super”,通过super引用可以得到父类的相关相关方法和属性,而且,这个super还是一个静态的。
其实,在你new子类(这里是B3类)的时候,它确实是按照那四部来的,第一步就是对B3类的属性做了初始化。但是,这里有一个隐式的属性值,写出来就是这样的:
private static 父类名 super = new 父类名();
并且是默认占有第一行,即总是第一个去执行。
所以,他会先去new一个A3类,然后由于是抽象类的实例化,这里又会动态绑定到B3类的方法,也就是print()实现方法的初始化。
这样,这里的this.i总是被初始化为0,因为并没有显示的初始化,所以System.out.println("i= "+this.i);} 和 System.out.println("i= "+i);}的打印结果一样,都是0,因为这个时候,还没有运行到“非静态方法的初始化”这一步来。
在之后,就是B3类里那个i的显示初始化了,由于没有自己的构造器,所以这里就没有显示了。

验证以上的方法:
你在B3类里,写一个自己的构造器,就调用那个print()方法,你会发现打印了两行数据:
i= 0
i= 2

具体代码如下:
abstract class A3 {
public abstract void print();
A3() {
print();
}
}

class B3 extends A3 {
private int i = 2;

//加构造器,测试一下看
public B3(){
print();
}
public void print() {
System.out.println("i= " + this.i);
}
}

public class Test314 {
public static void main(String[] args) {
B3 r = new B3();
}
}

以上就是基类初始化的实质所在了,绝对原创
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
a379933101
2010-08-06 · TA获得超过474个赞
知道小有建树答主
回答量:296
采纳率:0%
帮助的人:121万
展开全部
这个问题啊,恩,你在Test314的main方法中New B3 的时候,B3类中的 i=2没有执行,在你的程序中,new 的话,她只执行构造方法 B3(){},也就是在实例化B3的时候他只执行B3自己的默认构造方法,其余的没有不执行,也就是说在 B3 执行print()方法的时候,就相当于 i 没有 值,输出默认值 0 ,如果 i 是字符串的话,就会输出默认值 Null;

哪个this.i 和 i都是一样的,都是B3里面的那个i值
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 更多回答(2)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式