程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> 從stackoverflow上的一個問題看Java動態綁定,stackoverflowjava

從stackoverflow上的一個問題看Java動態綁定,stackoverflowjava

編輯:JAVA綜合教程

從stackoverflow上的一個問題看Java動態綁定,stackoverflowjava


我們先來看stackoverflow上的一個問題,先上代碼

 1 public class Piece{
 2     public static void main (String [] args){
 3         Piece p2 = new Knight();  
 4         Knight p1 = new Knight();
 5         p1.capture(p2);   
 6         p2.capture(p1);   
 7     }
 8     public void capture(){
 9         System.out.println("Capture");
10     }
11     public void capture(Piece p){
12         System.out.println("I'm bored");
13     }
14 }
15 class Knight extends Piece{
16     public void capture(Piece p){       
17         System.out.println("Knight is bored");
18     }
19     public void capture(Knight k){      
20         System.out.println("Too slow buddy");
21     }
22 }

問的是這段代碼輸出是什麼?答案是

Knight is bored
Knight is bored

因為剛剛開始學習Java,在跟CS61B的課,然後老師講到dynamic type和static type的時候,自己有點模糊,於是在stackoverflow上搜索相關的問題,果然發現一個典型的動態綁定的問題,仔細分析之後感覺收獲挺大的,對繼承的理解更加深入了。

分析:這個是怎麼回事呢?首先看第三第四行,p1肯定是一個Knight類型,而對於p2, 它是一個Piece類型的引用,指向了一個Knight類的對象,此時我們稱Piece為static type,而Knight為dynamic類型。

p1.capture(p2),也就是Knight.capture(Piece),Knight類裡剛好定義了這個方法,即輸出"Knight is bored"。

p2.capture(p1),也就是Piece.capture(Knight),乍一看Piece裡面沒有這個方法啊。這裡應該是有一個賦值,即Piece p = p1,把子類的引用賦給父類,這是允許的。所以實際上調用的Piece.capture(Piece),那麼結果應該輸出"I'm bored"啊,怎麼會是"Knight is bored"呢?前面已經說了,p2實際上指向了一個Knight類的對象,而在Knight類中剛好Ovriride了這個Piece.capture(Piece)方法,也就是Knight.capture(Piece),所以應該調用這個方法,即輸出"Knight is bored"。

 

好現在我們把這個Override的方法注釋掉,看看結果如何?

 1 public class Piece{
 2     public static void main (String [] args){
 3         Piece p2 = new Knight();  //static Piece, dynamic Knight
 4         Knight p1 = new Knight();
 5         p1.capture(p2);   
 6         p2.capture(p1);   
 7     }
 8     public void capture(){
 9         System.out.println("Capture");
10     }
11     public void capture(Piece p){
12         System.out.println("I'm bored");
13     }
14 }
15 class Knight extends Piece{
16     // public void capture(Piece p){       //這裡override了Piece中的方法
17     //     System.out.println("Knight is bored");
18     // }
19     public void capture(Knight k){      
20         System.out.println("Too slow buddy");
21     }
22 }

輸出結果是:

I'm bored
I'm bored

分析:第二個輸出剛剛已經解釋了,因為現在沒有override的方法了,所以就直接調用Piece類中的Piece.capture(Piece p)方法。那麼第一個輸出又是怎麼回事呢?p1.capture(p2),也就是Knight.capture(Piece),這裡不能調用Knight.capture(Knight k)這個方法,因為Knight k = p2,這是不合法的,Java中不允許把父類的引用賦給子類的引用變量。那麼既然如此,Knight類中豈不是沒有這個方法了嗎?不要忘記,Knight類是繼承在Piece類上的,也就是Knight類型也能調用Piece類中的方法,也就是Piece.capture(Piece)方法,所以輸出是"I'm bored"。

 

現在我們知道,Piece p2 = new Knight()這句特殊之處就在於,有一個查找在子類中是否存在override的方法,如果存在就調用子類中這個override的方法,如果沒有就使用父類中的方法。如果是這樣定義的:Piece p2 = new Piece(),那麼無論在子類中有沒有override方法,都不會去調用子類的方法,而是直接調用父類的方法。如下:

 1 public class Piece{
 2     public static void main (String [] args){
 3         // Piece p2 = new Knight();  //static Piece, dynamic Knight
 4         Piece p2 = new Piece();
 5         Knight p1 = new Knight();
 6         p1.capture(p2);   
 7         p2.capture(p1);   
 8     }
 9     public void capture(){
10         System.out.println("Capture");
11     }
12     public void capture(Piece p){
13         System.out.println("I'm bored");
14     }
15     public void capture(Knight p){
16         System.out.println("Hello");
17     }
18 }
19 class Knight extends Piece{
20     public void capture(Piece p){       //這裡override了Piece中的方法
21         System.out.println("Knight is bored");
22     }
23     public void capture(Knight k){      //這裡override了Piece中的方法
24         System.out.println("Too slow buddy");
25     }
26 }

輸出結果是:

Knight is bored
Hello

我們可以看到,即使在Knight類中override了.capture(Knight)方法,由於p2一直就是一個Piece類,根本不會調用Knight類中的方法,所以p2.capture(p1),也就是Piece.capture(Knight),輸出"Hello"。第四行改成Piece p2 = new Knight(),則輸出就是:

Knight is bored
Too slow buddy

第二個輸出調用的就是Knight類中override的方法。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved