有段代码如下:
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

解决方案 »

  1.   

    你是B的实例。B中覆盖方法init()后,可以看成父类中的init()方法已经不存在了只能调用子类的
      

  2.   


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

  3.   

    初始化B的实例的时候会先调用父类A的构造方法这个你知道吧?所以先输出P,然后调用init方法
    你也知道B覆盖了A的init方法,所谓覆盖,就是说盖上了不显示出来,所以A的init方法就不能显示出来咯
    所以输出了C 2
    后面那个1才是值得琢磨的东西!~
      

  4.   


    对啊,1是因为先super()后再进行初始化。
    可是对目前本题中this虽然写在TestA中,但它真正代表的是TestB而不是一般我们认为的TestA这个问题非常别扭!转不过弯来。
      

  5.   

    这应该是init调用的问题,父类进行调用,应该是虚拟调用,对子类不起效果,也就是说,这个时候的i不是子类的i,而是父类自己复制出来的i
      

  6.   

    B继承了A 的构造方法 
    而且你在B类重写了A类的init()方法,那必然是先找到子类的重写的init()方法(包含你把 i 的值 负成2),但你在B类的构造方法里输出了i (这个时候i的值是1)   
    所以输出是  p c 2 1 
      

  7.   

    类继承,你千万不要想成B类里面包含了一个A类,这个时候,系统里只有一个B类,没有A类这个东西。如果是属性,到还是有可能的,特别是直接访问一些private的属性,是没有override这个说法的,但方法绝对是。
      

  8.   

    不知道能不能这样理解
    你创建一个子类对象后
    在子类调用父类构造方法的时候 
    由于this始终是指向当前对象自己的(这里是指testb)
    父类的this隐藏了
    变成了super.this
      

  9.   

    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.
    }
      

  10.   

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

  11.   

    关于ZiSheng在第17楼的回复,我想改写成这样更好:
    初始化的顺序问题 
    1:父类的静态成员,静态块 
    2:子类的静态成员,静态块 
    3:父类执行构造函数,在构造函数中执行非静态成员,非静态块.
    4:子类执行构造函数,在构造函数中执行非静态成员,非静态块.之所以我自己这样认为,因为ZiSheng在16楼贴出来的反编译代码里已经显示了,非静态成员的初始化是在构造函数中进行的.
      

  12.   

    楼主回答的太完美了。学到不少东西。赞一个啊。可是当我
     TestA() 
          { 
                  System.out.println("P "); 
                  String s=this.getClass().getName();
                  System.out.println(s);//这里的s居然是TestB.为什么
                  this.init();//为什么this.init()调用的是已经被覆盖了的子类的init()了,而不是当前TestA的init()呢??? 
          } 
      

  13.   

    this是指向当前实例的引用,与被写在哪一个Class不是一一对应的,只是运行时这段代码所处的实例有关,只是实例是TestB的,所有这些this都会取到一个TestB的Class.