为什么this.init()调用的是已经被覆盖了的子类的init()了???

Sodino 2009-02-20 08:17:13
有段代码如下:
public class TestA
{
TestA()
{
System.out.println("P ");
this.init();//为什么this.init()调用的是已经被覆盖了的子类的init()了,而不是当前TestA的init()呢???
}
void init()
{
System.out.println("Q ");
}

public static void main(String[] args)
{
TestB testb=new TestB();
}
}

class TestB extends TestA
{
int i=1;
TestB()
{
super();
System.out.println(i+" ");
}
void init()
{
System.out.println("C ");
this.i=2;
System.out.println(i+" ");
}
}

运行后输出为:
p q 2 1

...全文
530 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
防空洞 2009-03-09
  • 打赏
  • 举报
回复
楼主回答的太完美了。学到不少东西。赞一个啊。可是当我
TestA()
{
System.out.println("P ");
String s=this.getClass().getName();
System.out.println(s);//这里的s居然是TestB.为什么
this.init();//为什么this.init()调用的是已经被覆盖了的子类的init()了,而不是当前TestA的init()呢???
}
防空洞 2009-03-09
  • 打赏
  • 举报
回复
恩。很正确。
cyberwjf 2009-03-09
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 ayiui4566 的回复:]
楼主回答的太完美了。学到不少东西。赞一个啊。可是当我
TestA()
{
System.out.println("P ");
String s=this.getClass().getName();
System.out.println(s);//这里的s居然是TestB.为什么
this.init();//为什么this.init()调用的是已经被覆盖了的子类的init()了,而不是当前TestA的init()呢???
}
[/Quote]
this是指向当前实例的引用,与被写在哪一个Class不是一一对应的,只是运行时这段代码所处的实例有关,只是实例是TestB的,所有这些this都会取到一个TestB的Class.
Sodino 2009-03-07
  • 打赏
  • 举报
回复
关于ZiSheng在第17楼的回复,我想改写成这样更好:
初始化的顺序问题
1:父类的静态成员,静态块
2:子类的静态成员,静态块
3:父类执行构造函数,在构造函数中执行非静态成员,非静态块.
4:子类执行构造函数,在构造函数中执行非静态成员,非静态块.

之所以我自己这样认为,因为ZiSheng在16楼贴出来的反编译代码里已经显示了,非静态成员的初始化是在构造函数中进行的.



[Quote=引用 16 楼 ZiSheng 的回复:]

引用 13 楼 rwqs05 的回复:
为什么最后一个是1啊

java编译之后对你的代码进行了优化,TestB就相当于:

Java code
class TestB2 extends Test
{

TestB2()
{
super();
i = 1; //非静态成员的初始化是在构造函数中进行的
System.out.println((new StringBuilder(String.valueOf(i))).append(" ").toString());
}

void init()
{
System.out.println("C ");
i = 2;
System.out.println((new StringBuilder(String.valueOf(i))).append(" ").toString());
}

int i;//把你的对i的初始化放到了构造函数里边,所以结果变为了1.
}




[/Quote]



[Quote=引用 17 楼 ZiSheng 的回复:]

其实也就是在类被家在后,初始化的顺序问题
1:父类的静态成员,静态块
2:子类的静态成员,静态块
3:父类的非静态成员,非静态块,构造函数
4:子类的非静态成员,非静态块,构造函数
实际是在第四步,父类的构造函数执行完毕后就会执行int i=1;
然后是TestB的构造函数。执行
System.out.println(i+" ");
输出结果为1

[/Quote]
Wbl314 2009-02-21
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 sodino 的回复:]
引用 6 楼 rypgood 的回复:
初始化B的实例的时候会先调用父类A的构造方法这个你知道吧?所以先输出P,然后调用init方法
你也知道B覆盖了A的init方法,所谓覆盖,就是说盖上了不显示出来,所以A的init方法就不能显示出来咯
所以输出了C 2
后面那个1才是值得琢磨的东西!~


对啊,1是因为先super()后再进行初始化。
可是对目前本题中this虽然写在TestA中,但它真正代表的是TestB而不是一般我们认为的TestA这个问题非常别扭…
[/Quote]
不知道能不能这样理解
你创建一个子类对象后
在子类调用父类构造方法的时候
由于this始终是指向当前对象自己的(这里是指testb)
父类的this隐藏了
变成了super.this
paullbm 2009-02-21
  • 打赏
  • 举报
回复
楼主PQ21?
rwqs05 2009-02-21
  • 打赏
  • 举报
回复
为什么最后一个是1啊
老紫竹 2009-02-21
  • 打赏
  • 举报
回复
类继承,你千万不要想成

B类里面包含了一个A类,

这个时候,系统里只有一个B类,没有A类这个东西。

如果是属性,到还是有可能的,特别是直接访问一些private的属性,是没有override这个说法的,但方法绝对是。

xiaokss77 2009-02-21
  • 打赏
  • 举报
回复
B继承了A 的构造方法
而且你在B类重写了A类的init()方法,那必然是先找到子类的重写的init()方法(包含你把 i 的值 负成2),但你在B类的构造方法里输出了i (这个时候i的值是1)
所以输出是 p c 2 1
ZiSheng 2009-02-21
  • 打赏
  • 举报
回复
家在-》加载
ZiSheng 2009-02-21
  • 打赏
  • 举报
回复
其实也就是在类被家在后,初始化的顺序问题
1:父类的静态成员,静态块
2:子类的静态成员,静态块
3:父类的非静态成员,非静态块,构造函数
4:子类的非静态成员,非静态块,构造函数
实际是在第四步,父类的构造函数执行完毕后就会执行int i=1;
然后是TestB的构造函数。执行
System.out.println(i+" ");
输出结果为1
YL_Show 2009-02-21
  • 打赏
  • 举报
回复
Mark
ZiSheng 2009-02-21
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 rwqs05 的回复:]
为什么最后一个是1啊
[/Quote]
java编译之后对你的代码进行了优化,TestB就相当于:

class TestB2 extends Test
{

TestB2()
{
super();
i = 1;
System.out.println((new StringBuilder(String.valueOf(i))).append(" ").toString());
}

void init()
{
System.out.println("C ");
i = 2;
System.out.println((new StringBuilder(String.valueOf(i))).append(" ").toString());
}

int i;//把你的对i的初始化放到了构造函数里边,所以结果变为了1.
}
ZiSheng 2009-02-21
  • 打赏
  • 举报
回复
[Quote=引用楼主 sodino 的帖子:]
public class TestA
{
TestA()
{
System.out.println("P ");
this.init();//为什么this.init()调用的是已经被覆盖了的子类的init()了,而不是当前TestA
//init()呢???
//这个this是会随着你创建的实际对象而不同的,你加上this.getClass().getName();在创建个
//TestA类的对象试试

}
void init()
{
System.out.println("Q ");
}

public static void main(String[] args)
{
TestB testb=new TestB();
}
}

class TestB extends TestA
{
int i=1;
TestB()
{
super();
System.out.println(i+" ");
}
void init()
{
System.out.println("C ");
this.i=2;
System.out.println(i+" ");
}
} [/Quote]
rypgood 2009-02-20
  • 打赏
  • 举报
回复
这应该是init调用的问题,父类进行调用,应该是虚拟调用,对子类不起效果,也就是说,这个时候的i不是子类的i,而是父类自己复制出来的i
Sodino 2009-02-20
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 rypgood 的回复:]
初始化B的实例的时候会先调用父类A的构造方法这个你知道吧?所以先输出P,然后调用init方法
你也知道B覆盖了A的init方法,所谓覆盖,就是说盖上了不显示出来,所以A的init方法就不能显示出来咯
所以输出了C 2
后面那个1才是值得琢磨的东西!~
[/Quote]

对啊,1是因为先super()后再进行初始化。
可是对目前本题中this虽然写在TestA中,但它真正代表的是TestB而不是一般我们认为的TestA这个问题非常别扭!转不过弯来。
rypgood 2009-02-20
  • 打赏
  • 举报
回复
初始化B的实例的时候会先调用父类A的构造方法这个你知道吧?所以先输出P,然后调用init方法
你也知道B覆盖了A的init方法,所谓覆盖,就是说盖上了不显示出来,所以A的init方法就不能显示出来咯
所以输出了C 2
后面那个1才是值得琢磨的东西!~
一洽客服系统 2009-02-20
  • 打赏
  • 举报
回复
差点因为结果迷糊了 还跳着运行:(
Sodino 2009-02-20
  • 打赏
  • 举报
回复
啊!!我写错了,输出结果是 P C 2 1
Sodino 2009-02-20
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 sbfivwsll 的回复:]
你是B的实例。B中覆盖方法init()后,可以看成父类中的init()方法已经不存在了。。。只能调用子类的
[/Quote]

这么说的话,this并不代表其所在的当前类了??例如本题中this虽然写在TestA中,但它真正代表的是TestB而不是一般我们认为的TestA??这就是我觉得别扭的地方。是吗?如何理解这个怪异的现象呢?谢谢。。。。。
加载更多回复(2)

62,614

社区成员

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

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