2011-03-13 207 views
2
class Base 
{ 
    int i = 99; 
    public void amethod() 
    { 
     System.out.println("Base.amethod()"); 
    } 

    Base() 
    { 
     amethod(); 
    } 
} 
public class Derived extends Base 
{ 
    int i = -1; 

    public static void main(String argv[]) 
    { 
     Base b = new Derived(); 
     System.out.println(b.i); 
     b.amethod(); 
    } 

    public void amethod() 
    { 
     System.out.println("Derived.amethod()"); 
    } 
} 

爲什麼這個代碼打印b.i = 99而不是b.i = -1? 謝謝。Java代碼說明

回答

4

這是因爲你引用的對象的成員變量而不是一種方法。由於它被聲明爲Base對象,因此它將使用Base.i,因爲成員變量不受益於方法提供的多態性。如果你爲這兩個類添加了一個getI()方法並且調用了它,而不是僅僅使用b.i,它就會像你期望的那樣工作。

public int getI() { 
    return this.i; 
} 


    Base b = new Derived(); 
    System.out.println(b.getI()); 
+0

爲什麼Base()構造函數在Derived中調用amethod()?如果你可以解釋 – Kobe 2011-03-13 18:26:07

+0

因爲當你在一個對象上調用一個方法時,它會調用真實類型的對象的方法。所以即使你在Base構造函數中,當你調用amethod()時,它開始在子類中尋找amethod()實現。如果它沒有在那裏找到一個,那麼它會向上移動繼承層次結構,但它總是首先嚐試子節點。 – 2011-03-13 18:29:51

+0

謝謝你,我明白了 – Kobe 2011-03-13 18:32:07

2

你有兩個不同的字段名爲i;一個在Base,另一個在Derived

b由於被聲明爲Baseb.iBase類返回i字段。

您可能想要在Derived構造函數中設置i字段,而不是創建新字段。

1

方法可以被覆蓋,但字段掩碼,所以你的子類定義了一個名爲i的新字段。超類方法指的是在超類中定義的舊字段i

2

因爲在這種情況下b.i說((Base).i)意味着它會引用Base的i變量而不是Derived i。如果你做了b.getI(),並且每個Base和Dervid實現了自己的getI並返回它們自己的i,它將返回-1。

解釋爲什麼Base調用Derived的amethod。 Java方法調用是動態的,並在運行時確定。在你的情況Base b = new Derived() b這裏是Derived類型。 Java運行時會實現b的類型,並調用最接近Derived創建的方法。

所以,如果你有

class Base{ 
    int i =99; 
    public int getI(){ 
    return i; 
    } 
} 
class Derived extends Base{ 
    int i =-1; 
    public int getI(){ 
    return i; 
    } 
} 

Derived的哥提()方法將被調用(和返回-1),即使其定義爲Base b = new Derived();