2012-11-27 111 views
3

請考慮下面的代碼片段。我瞭解如何覆蓋泛型類型,以及爲什麼返回類型List<String>(例如)被允許覆蓋List<? extends Object>。然而,我不完全清楚爲什麼像1和2這樣的陳述不能編譯......不應該在這裏也適用繼承嗎?通用返回類型 - 爲什麼我不能這樣做?

public class Generics { 

    public static void main(String[] args) { 

     A instance = new B(); 
     X instance2 = new Y(); 

     Map<String, String> map = instance2.getMap(); // 1 
     List<String> list = instance.getList();  // 2 
    } 
} 

class A { 

    List<? extends Object> getList() { 

     return null; 
    } 
} 

class B 
     extends A { 

    List<String> getList() { 

     return new LinkedList<String>(); 
    } 
} 

class X { 

    Map<String, ? extends Object> getMap() { 

     return null; 
    } 
} 

class Y 
     extends X { 

    @Override 
    Map<String, String> getMap() { 

     return null; 
    } 
} 
+0

我知道已經有答案了,但是可以發佈編譯器錯誤嗎? – Jerome

+0

對不起,我收到了一個普通的靜態類型檢查錯誤(即「不能從列表<?extends Object>轉換爲列表)。 – csvan

回答

3
Map<String, String> map = instance2.getMap(); // 1 

編譯器看到到X.getMap()調用其中有Map<String, ? extends Object>返回類型。這不能兌換成Map<String, String>。在運行時,instance2的類型是Y並不重要;這是純粹的編譯時靜態類型檢查失敗。

List<String> list = instance.getList();  // 2 

同樣的推理適用。編譯時類型instanceA,並且A.getList()返回與List<String>不兼容的List<? extends Object>

請注意,這不是泛型的具體問題。這也將無法編譯出於同樣的原因:

class A { Object getObject(); } 
class B extends A { String getObject(); } 

A a = new B(); 
String s = a.getObject(); 

如果你想它的工作,那麼你需要給編譯器一些額外的幫助。無論是通過強制轉換爲子類:

String s = ((B) a).getObject(); 

或者通過鑄造返回值:

String s = (String) a.getObject(); 
+0

+1與我的答案類似,我現在刪除:) –

+0

非常很有幫助,非常感謝! – csvan

1

多態性不能向後工作。

如果你試過用不同的類,它擴展X,但它歸還給你一個\

Map<String, NonString> 

呢?

0

您正在呼籲XgetMap(因爲instance2是通過X引薦),它被定義爲返回Map<String, ? extends Object>因此這個問題。

如果你改變你的電話爲(主叫getMap()之前強制轉換instance2Y):

Map<String, String> map = ((Y)instance2).getMap(); // 1 

它應該作爲您instance2Y型的還是。

相關問題