Thinking In Java中说,this关键字是对"调用这个方法和属性的对象的引用",那么按照这个逻辑去理解
public class A{
  
  publi int i = 0;
  public void test(){
    System.out.print(this.i);
  }}public class B extends A{
 
  public int i =1;  public static void main(String[] args){
     A a = new B();
     a.test();
  }}按照这样理解话,a对象调用父类的test方法时,this指的就该是a对象的i,也就是1,但这显然是错误的。我的理解错误在哪呢?

解决方案 »

  1.   

     A a = new B(); 
        a.test(); 
    你这是new B();  this自然代表B类的对象
      

  2.   

    A a = new B(); 得到的是一个A类型的B实例,this指向B实例,而不是A
    去看下多态
      

  3.   

    晕 CSDN又抽风了是这样的
    A a = new B();
    然后调用a.test();方法
    B并没有重写test();方法
    所以调用的还是A中的test();方法
    这样就向上转移到父类A中
    执行A中的test();方法
    test();方法执行System.out.print(this.i); 
    注意~这个时候执行代码处于A类中所以i是0
      

  4.   

    首先是有了你类A 才会有你后面的代码 public class B extends A{ ,所以this.i不可能是1, 而且你的this又没经过引用传递(应该也不可能),  所以我觉得this 就是本身对象的引用,不知道对不对
      

  5.   

    正是因为this指向的是B实例,所以才让我困惑,因为在B实例中的i值是为1的
      

  6.   

     ---------------------
     |
    B|   int i = 1;
     | -------------------
     | | int i = 0;
     | | 
     |A|------------------
     | | test();
     | |------------------
     |-------------------- A a = new B(); 
    这个时候的a只是下面属于A的部分。
    不知道这样是不是对你有用。
      

  7.   

    晕倒狂晕
    this指向当前类的实例,这个当前类指的是该this所处的那个类(这里就是A类)
      

  8.   

    自己test了下,输出的是0
    因为是调用的A类的方法,所以this指的是A的成员变量
      

  9.   


    this指向当前类的实例,这个当前类指的是该this所处的那个类(这里就是A类)
      

  10.   

    详细分析:public class A{ 
      
      publi int i = 0; 
      public void test(){ 
        System.out.print(this.i); 
      } } public class B extends A{   public int i =1;   public static void main(String[] args){ 
        A a = new B(); //这里是一个A类的引用,指向的是A类的子类B的一个对象
        a.test(); //可能涉及多态,但要注意,这里a就是一个A类型的引用,B类并没有覆盖父类的test()方法,所以还是调用父类A的方法test,这样以来,肯定是i=0的了,哪有这么复杂
      } } 
      

  11.   

    继续分析:如果楼主在B类中重写test()方法的话,结果就是i=0了,因为这就成为了真正的多态了,经过测试验证正确。代码如下class A{ 
      
      public int i = 0; 
      public void test(){ 
        System.out.print(this.i); 
      } } public class B extends A{   public int i =1; 
      
      public void test() {//增加此方法,重写
       System.out.print(i);
      }  public static void main(String[] args){ 
        A a = new B(); 
        a.test(); 
      } } 
      

  12.   

    test()方法是属于A类的,相应的变量也应该是A类对象的i。
    如果像这种情况一般都是要在子类重载父的方法,也就是说在B类中应该定义一个test()方法。
      

  13.   


    是自己猜的吧, 实际上未必如你所说, 看看以下代码, 按照你的说法是test()是在A类中的,所以 test()内部的 this 就是指A类, 如果是这样,那么你猜一下, 执行this.getI() 返回的值是什么? 是"0"吗?    答案应该是"1"! 
    现在问题来了,为什么 this.i 返回是0, this.getI() 返回是1呢, 我不是专家,我不敢乱猜,等高手来解释吧. 
     class A { public int i = 0; public void test() {
    System.out.print(this.getI());
    } public int getI() {
    return i;
    } public void setI(int i) {
    this.i = i;
    }}class B extends A { public int i = 1; public int getI() {
    return i;
    } public void setI(int i) {
    this.i = i;
    }}
      

  14.   

    程序是这样执行的:A a = new B();
        系统在栈中为a 的引用分配一块内存,指向堆中的B的对象的实例,由于是父类的对象指向子类的引用,但是子类并没有重写父类的方法test();所以并没有多态存在,子类的成员变量 i = 1 父类是不能够访问的;当系统调用test()方法是自然不会有多态产生,也就不会访问子类的成员变量i.
      

  15.   

    上面吵的很火啊,哈哈,兄弟,我和你说,你的问题是多态没搞明白!和你说下吧。
    在运行时,记住,是运行时,不是编译时,JAVA多态的三大要点:
    1、实例方法与引用变量实际引用的对象的方法绑定,这种绑定属于动态绑定,因为是在运行时由Java虚拟机动态决定的。
    2、静态方法与引用变量所声明的类型的方法绑定,这种绑定属于静态绑定,因为实际上是在编译阶段就已经做了绑定。
    3、成员变量(包括静态变量和实例变量)与引用变量所声明的类型的成员变量绑定,这种绑定属于静态绑定,因为实际上是在编译阶段就已经做了绑定。
    这里我们关注上面的第三点!
    为什么运行结果是“0”呢,因为在test()方法中调用了成员变量。这里的this.i,this指的是B类型的对象,这大家都赞同,但是这个B类型对象的引用变量a却是声明为A类型的,所以,这里的this.i的成员变量i是与A类型中的成员变量i绑定在一起的。所以结果是“0”。
      

  16.   

    首先谢谢大家的帮助,以前学的不扎实,现在来看果然问题很多,呵呵。
    关于A a = new B();a.test(); 这里相信很多人都被束缚了,这和new B().test()有什么区别?没有区别。a这个引用这是用来控制new B()的行为而已。22楼的兄弟的说法我认为是恰当的,test()方法在父类,而父类的方法是无法访问子类属性的。所以i=0。而父类当中的this也并不指的是当前类的实例,还是Thinking In Java当中的那句话,谁调用这个方法this就指谁。
    大家可以在A类的test()方法中打印this.getClass(),得到的结果是B类,而并不是A类。
      

  17.   

    23楼的兄弟,如果照你这么说的话,我改成B b = new B();就与B类型中的成员变量绑定在一起,打印的就是1了?你试试呢,显然不对。
      

  18.   

    ~~仿佛看的出原因来,但是一时半会儿说不上来。
    这种情况也只会在继承碰到,如果A和B不是继承关系,那不可能一个对象去调用A中的方法结果是得到自己的属性,首先在A种定义这个不属于自己的属性的时候就会有错。
    所以我姑且认为  
    public void test(){ 
        System.out.print(this.i); 
      } 这个this.i在A中,所以是指的A的i....过几天再来看更微妙的答案
      

  19.   

    4种都试了
    A a = new A();
    A a = new B();
    B a = new B();
    B a = new A(); //这条当然是不行的
    也在子类里重写了test方法
    甚至把this也去掉了直接打i发现:
    LZ这个例子貌似不是阐述this关键字的好例子
      

  20.   

    唉 要不清楚 可别瞎说 误人子弟
    子类中有个父类对象super  
    a 引用动态绑定的是 B 
    a.test()相当于 在子类中调用 super.test() 
    这时的 this 指的是 super 也就是 A对象所以i是A中的属性i 
      

  21.   

    A类中的i=0
    B类中的i=1
    B继承A   A类中都为public 所以全部继承 
    注:A类有public int i = 0; 
       B类有public int i = 1; 
    B继承A  发生覆盖
    这时可以理解B类为
    public class B(
         public int i = 0;
         public void test(){ 
        System.out.print(this.i); 
      } )
    这时this指向的i就是0啦
      

  22.   

    大家都是猜的,有没有权威的资料来解释这个问题? 还有我在20楼,发的情况,把i 改成用getI()方法调用,就会变成1了.  this 应该是指向B, 但为什么this.I 却得到0呢? 用this.getI()得到的是1.   
      

  23.   

    楼主在B类代码中加上
    public void test(){ 
      super.test();
       // System.out.print(this.i); 
      } 
    看一下输出也许有助于理解
      

  24.   

    同意18楼所说的,问题就发生在没有覆盖父类的test()
      

  25.   


    在父类中this.i调用的是父类本身定义的变量i,即当前类中的变量i
    而getI()中调用的i是当前对象的变量值,即被子类覆盖的i值
    A a = new B();后
    A:i(0) <==> B: super.i(0)
    A: this.i(0) <==> B: super.i(0)
    B: this.i(1) <==> B: i(1)
      

  26.   

    如果B没有重写test();
    无论A a = new B(); 还是 B a = new B(); 
    输出i都是0, 可见是调用了A的test(),里面的this指向A如果B重写test();
    无论A a = new B(); 还是 B a = new B();
    输出i都是1
    当A a = new B();时,多态
    当B a = new B();时,就直接调用自己的test();不知道这样理解对不对
      

  27.   

    class A {
    private int i=0;
    public void test() {
    System.out.println(this.i); //this.i是引用该类中的成员变量i
    }
    }
    public class B extends A {
    private int i=1; public static void main(String[] args) {
    A a = new B(); // 首先new出一个B类的实例,然后向上转型为A类,然后执行A类的test()方法;不过B类的继承A类的时候没有重写A类的test()方法,所以        a.test()依然是调用A类的test()方法.因此结果是 0.
    a.test();  }}
      

  28.   

    呵呵 看来这个问题有向String对象那个问题靠拢的趋势了
      

  29.   

    同意29楼的,应该是从A类中继续的i覆盖了B类中声明的i,那B类的的i也变成了0,输入当然就是i=0啦
      

  30.   

    恩,我后面又重新测试了一下,JAVA多态的三大要点对(对成员方法有效),而对于成员变量,如果方法调用成员变量,是调用与这个方法在同一个类中的成员变量。
      

  31.   

    在内存堆中每new一个对象, 这个对象都会隐式的持有this和super两个对象的引用. 
    this指的是自身, super指的是父类(猜测一下:单继承或许就是为了这个super的便于管理)
    如楼主代码, 在main方法执行过程中, A a = new B(); 虽然只在堆中new了一个B的实例对象, 但是, 这个对象其实不仅有一个this的引用指向自身, 还有一个super的引用指向一个父类的实例. 这个时候, 我们就可以比较容易理解多态以及楼主的问题了, 在计算机领域, 优先级永远都是局部大于全局, this中有, 就用this, this中没有就找super, super本身还有super, 直到找到为止. 对于楼主的问题, 由于B类没有重写test方法, 所以使用的是super引用指向的对象的方法, 那么结果是什么, 可向而知.
    对于20楼朋友提出的getI()方法的现象, 还用解释了吗? this指向的对象(也就是自身)所属的类已经重写了getI()方法, 局部大于全局, 执行this指向的对象的方法, 结果不是一目了然吗?
      

  32.   

     把这一句:System.out.print(this.i); 
       改成这个:System.out.print(this.getClass().getName());看看,this指向的是B!但是为什么第一句是0,我不知道。
      

  33.   

    《Java Rules》的3.4节说this是多态的。3.4.1的第一个例子与这个几乎一样,只不过输出了this指向的类名。
      

  34.   

    A a = new B(); a.test();很明显你此时的在test里边的this是B类的对象,而你的B类有两个i域,这时的i指的是父类的i
    在子类中你用this.i指的是子类的i,你想要在子类中调用父类的i,super.i
      

  35.   

    我也觉得this指向的是B,因为调用getClass().getName()方法显示的就是B,应该调用子类的i,但是为打印出来的是0呢?
      

  36.   

    我知道啦,这是域的隐藏!!!当子类中定义了与父类同名的属性变量,即出现了子类变量对同名父类变量的隐藏。这里所谓的隐藏是指子类拥有了两个相同名字的变量,一个继承自父类,另一个由自己定义;当子类执行继承自父类的操作时(这里是test()),处理的是继承子父类的变量(这里是i=0),而当子类执行他自己定义的方法时,所操作的就是他自己定义的变量(i=1),而把继承自父类的变量隐藏起来。楼主的test里的this指的是B类,不信可以调用this.getClass().getName()看看结果。问题解决!!
      

  37.   

    补充一句:this是多态的。如果this关键字所在的那个类的成员被一个子类继承,那么this关键字引用的那个对象的类就是子类。    这只是this多态的表现之一,还有其他的。
      

  38.   

    A a = new B(); 
    父类对象实例化了子类B ,如果子类B中没有重写或重载test方法,那a.test()方法调用的是A类的test方法  i是0啊
      

  39.   

    this  指当前类的实例 
    this.i 调用当前类的成员变量
    当父类的引用指向子类的对象时,当前的this当然指向的是父类中的i 
    输出0
      

  40.   

    这是《java语言与面向对象程序设计》印旻著,清华大学出版社。是对域的隐藏的原话。