一个Java的小问题

  老师今天在讨论群里抛出了一个问题,让大家尝试思考一下他所给的一段代码输出是什么。

  其代码如下:

  

class T {
    void foo() { this.bar(); }
    void bar() { System.out.println("T.bar"); }
    public static void main(String args[]) {
        B b = new B();
        b.foo();
    }
}

class B extends T {
    void foo() { super.foo(); }
    void bar() { System.out.println("B.bar"); }
}

  思考了一波:

    实例化子类对象,子类父类都没有显式构造器,就是在子类父类方法之间跳来跳去的。

  “嗯,答案一定是'T.bar'”。

  但还是敲了一遍,发现答案竟然是'B.bar'......(如图)

  室友说:“对啊,this不就是指向当前对象嘛...”

  (啪,打脸...疼...)

  重新审视了一遍,才发现自己对于this还是没理解到位...

  也就是说,整段代码执行流程如图:

  问题就在于this.bar()的指向问题... 平时一般遇到this一般都会在本类里(这里就是T类)去找是否有将之实现的方法,若有,就是它了。

  但是这次不同,事实上,正是this,使得当前方法指向其具体的对象,当这个对象实现了这个方法(这里的B类里将bar()方法覆盖了),自然this.bar()就会指向子类实现的这个bar()方法。

  本质上,输出B.bar是方法覆盖的问题,但自己犯错的原因是this的指向问题。

  因此,当我们稍微改一下代码。

  将B类的bar方法注释掉,让其不能覆盖其父类T的bar方法,结果this依旧是指向B类对象,但要调用bar方法时,发现B类没有bar方法的实现,因此“追溯”到B的父类中去寻找bar方法,此时找到了父类的bar方法并将其调用,输出自然也就是T.bar(如图)。

  

  此时,再来看另一种改动:只是在父类T中删掉了this,运行结果如图:

  可以看到,程序的输出结果依旧是B.bar。(这或多或少超出了我的预料)

  也就是说,这时的程序,和含有this关键字时,是一样的......

  这道题给我的印象还是很深刻的,毕竟自己看完题之后,竟然一点儿都不谦虚地直接喊出了一个错误答案...

  以后一定会多多注意this和super这样的很容易“改变”程序流程的关键字...

原文地址:https://www.cnblogs.com/stevenshen123/p/8625326.html