2015-05-04 28 views
0
class G { 

    int x = 5; 
} 

class H extends G { 

    int x = 6; 
} 

public class CovariantTest { 

    public G getObject() { 
     System.out.println("g"); 
     return new G(); 
    } 

    public static void main(String[] args) { 
     CovariantTest c1 = new SubCovariantTest(); 
     System.out.println(c1.getObject().x); 
     System.out.println(new H().x); 
    } 
} 

class SubCovariantTest extends CovariantTest { 

    public H getObject() { 
     System.out.println("h"); 
     return new H(); 
    } 
} 

輸出:爪哇 - 與協變類型WRT變量重寫

h 
5 
6 

顯然,這兩個的println在main方法聲明是不一樣的。從類SubCovariant的getObject方法返回的新H()對象如何分配給G引用?

+2

**你永遠不會得到* 5作爲輸出* 與您發佈的代碼!! ** –

+0

似乎有一個錯字錯誤。某處x應該是5'int x = 5;' – Kartic

+0

謝謝..編輯int x = 5; – rpg

回答

1

G是聲明的類型,H是實際的類型。

聲明的類型就是你可以想象的那個對象,例如你的例子中的G。

實際的類型是對象實際是什麼,即在你的例子中的H.這提供了實際的行爲,包括它可能從父類繼承的任何行爲,包括G.

1

當您重寫某個方法時,它是重要實例的類型,而不是引用的類型。這就是多態性是如何工作的。

CovariantTest c1 = new SubCovariantTest(); 

這將轉換引用的類型,但不轉換實現。如果你是做

System.out.println(c1.getClass()); 

這將打印

SubCovariantTest 

所以,當你在這個實例調用getObject(),它應該是毫不奇怪,這要求SubCovariantTest.getObject()


相比之下,方法不遵循多態性。它們不能以相同的方式覆蓋(只能隱藏)如果要在兩種情況下使getObject()爲靜態,您會發現c1.getObject()將調用匹配c1的類型,因爲調用的方法是在編譯時確定的,而不是運行。事實上,你可以做到這一點。

public class CovariantTest { 

    public G static getObject() { 
     System.out.println("g"); 
     return new G(); 
    } 

    public static void main(String[] args) { 
     CovariantTest c1 = null; 
     System.out.println(c1.getObject().x); // prints "g" "5" 
    } 
} 

class SubCovariantTest extends CovariantTest { 

    public H static getObject() { 
     System.out.println("h"); 
     return new H(); 
    } 
} 

你可以在這裏訪問null參考,因爲它不是在運行時使用。編譯器只使用引用的類型,就像您在問題中預期的那樣。