螺 丝 钉 阅读(143) 评论(0)

    最近博客里有人问继承与this的问题。今天就这个问题以我的理解,做个说明。

问题的原貌:

public class Father {
   public int a = 10;

   public void test() {
      System.out.println(this.a);
   }

   public static void main(String[] args) {
      Son son = new Son();
      son.test();
   }
}

class Son extends Father {

   public int a = 20;

}

 

上面代码执行结果是10,提问者想知道test()方法执行时,this是Son的对象还是Father的对象。

 

这个问题其实是关乎到对于继承和方法重写的理解问题。

 

以下是我对继承和重写的理解:

继承:表示可以使用。作用是:代码复用,可以使用代码,但不是自己的

重写:表示真正拥有。作用是:个性化定制,让自己真正拥有

 

就拿上面的例子来说:

Father类中定义了字段a和方法test()。这意思就是说:Father类的对象会拥有test方法和a字段。a,test()都是public,那么它的子类就能够看到a和test(),就能使用它们了。

Son类中定义了字段a,表示Son类的对象会真正的拥有a。这样一来Son的对象就能自己拥有一个字段a,并且也能看到父类中的a。

 

上面的main方法中代码执行过程中:

son.test(),JVM发现son不拥有test(),就去它的父类找test(),找到后就把son对象作为一个Father对象来看,所以执行test(),取的是Father中的a,所以结果是10。

 

调整上面的代码如下:

public class Father {

   public int a = 10;
   public void test() {
      System.out.println(this.a);
   }

   public static void main(String[] args) {
      Son son = new Son();
      son.test();

   }
}

class Son extends Father {

   public int a = 20;
   public void test() {
      System.out.println(this.a);
   }
}

 如果在Son重写了test(),那就代表Son类的对象拥有test(),同时也能看到父类的test()。在执行test时,在Son类中能够找到test(),就直接执行test()。所以结果应当为20。

 

再次对代码调整:

public class Father {
   public int a = 10;

   public void test() {
     System.out.println(this.a);
   }

public static void main(String[] args) { Son son = new Son(); son.test(); Father fa=(Father)son; fa.test(); } } class Son extends Father { public int a = 20; public void test() { System.out.println(this.a); } }

在main方法中,执行son.test(),结果为20,上面已经说明为何了。

然后又强制转为Father对象fa。此时执行test()是谁的呢?

 

此时执行的test(),仍旧是son的。虽然强制转为Father对象,但她实质还是一个son,JVM检测出他是Son的实例,就查Son类中是否有test方法,有则执行。没有则查看父类Father。

 

整个过程中this一直都是指向son ,这个与JVM把它当做谁的对象是无关的。

执行谁的方法呢?要根据this关键字了。根据this关键字确认对象属于哪个类,查找这个类是否拥有这个方法,不拥有就去查父类有没有。