2013-07-26 38 views
0
class BaseClass { 
    int data = 101; 
    public void print() { 
     System.out.print(data + " "); 
    } 
    public void fun() { 
     print(); 
    } 
} 

class SubClass extends BaseClass { 
    int data = 202; 
    public void print() { 
     System.out.print(data + " "); 
    } 
} 

class TestClass { 
    public static void main(String[] args) { 
     BaseClass obj = new SubClass(); 
     obj.print();//call 1 
     obj.fun();// call 2 
     System.out.print(obj.data);//call2 
    } 
} 

所以我有一個父/子關係類和一個具有call1,call2,call3的測試類。這些父母和孩子課程的解釋?

1:關於CALL1,我的理由是,由於打印()正在由子類覆蓋和函數調用將打印數據正確的變量。這似乎是正確的,因爲這是正確的答案。

2:現在關於CALL2,因爲好玩的是隻存在於父類,所以呼叫將去那裏,理想情況下應該調用父類和輸出父類的數據變量樂趣方法。這不是正確的答案,根據答案它輸出數據的孩子類。

誰能給我解釋一下,什麼是錯我的推理?

回答

4

這是由於polymorphism。您覆蓋孩子中的print()方法,以便當子實例調用fun()時,它會調用它的方法print()的子類版本。

由於實例是子類,它將使用它具有的方法版本,而不是它的父類。

在JVM如何解決它的方法一個很好的資源,可以發現here

+1

+1正確的答案,但沒有完成什麼'System.out.print(obj.data);'? –

+0

@SubhrajyotiMajumder該部分很簡單,在實例變量的情況下不存在重寫,而變量指的是對象的原始類型。 – Dude

+0

暗示措辭:「對象的原始類型」有點......奇怪。一個對象只有一個類定義。施工後不能改變。 (當然,一個對象可以有幾種類型,它的定義類,每個超類以及它們實現的每個接口。)你的意思是編譯時的類型分辨率。編譯器只考慮聲明的類型。在這種情況下,變量「obj」的聲明類型是BaseClass。 – Seelenvirtuose

1

現在關於CALL2,因爲好玩的是隻存在於父類,所以 呼叫將去那裏,理想情況下應該調用有趣的方法 父類,並輸出父類的數據變量。這是 不是正確答案,根據回答它輸出的數據爲 子類。

這是不正確的。 BaseClassfun()將調用Subclassprint(),因爲它被覆蓋。 運行時多態性適用於此處。

1
 
    case 1 : obj.fun(); 

您已覆蓋print();方法。
在運行時,java根據對象類型解析方法調用。
所以這裏搜索方法fun()首先在​​,它沒有找到方法有,
因爲你​​沒有它(你是不是overrridden fun()那裏),並
然後去BaseClass(父)並在那裏找到fun()方法。

然後有一個方法print()它必須執行。
這裏也遵循相同的程序,首先在​​中搜索並在​​本身中找到print()
並執行它

所以這是你可以得到這樣的結果。

 
    case 2 : System.out.println(obj.data) 

這裏data是可變的,
編譯器只考慮申報類型的解析時獲得的變量(以及當解決超載)
這裏聲明的類型是BaseClass變量,所以結果是101

如果你創建一個這樣

SubClass obj2 = new SubClass(); 
    System.out.println(obj2.data); 

對象,然後結果將是202。既然聲明類型爲「子類」。

+0

這裏的措辭的另一個提示是:「變量總是基於不基於對象類型的引用類型來解析」。解釋類型概念時,JLS在基本類型和引用類型之間不同。所以在這種情況下,「參考類型」的措詞並不是真的正確。正確的是:編譯器只在解析對字段的訪問時(以及在解決重載時,只考慮變量的聲明類型)。 – Seelenvirtuose

+0

@Seelenvirtuose你是對的。我通過編輯糾正了這個問題。非常感謝你糾正我。 – Prabhaker