2011-10-14 100 views
11

讓我們有下面的類層次結構:Java泛型錯誤?

public class MyType { 
} 

public class MySuperclass<T extends MyType> { 
    protected Map<String, String> myMap = new TreeMap<String, String>(); 
    protected String myMethod(String s) { 
     return myMap.get(s); 
    } 
} 

public class MySubclass extends MySuperclass { 
    @Override 
    protected String myMethod(String s) { 
     return myMap.get(s); // <-- compilation error 
    } 
} 

爲什麼存在的MySubclass的覆蓋方法編譯錯誤? 錯誤消息是「類型不匹配:無法從對象轉換爲字符串」。

有趣的是,編譯錯誤自敗,如果我在MySubclass定義定義泛型MySuperclass類類型:

public class MySubclass extends MySuperclass<MyType> { 
    @Override 
    protected String myMethod(String s) { 
     return myMap.get(s); 
    } 
} 

有人可以解釋這種現象?我會認爲它是一個Java編譯器錯誤。

我正在使用jdk1.6.0_24。

回答

12

這不是一個錯誤。通過擴展MySuperclass而不是MySuperclass<MyType>,可以擴展原始類型MySuperclass,這意味着myMap也將是Map而不是Map<String, String>

+1

正好。那是布洛赫的「困惑者」之一。 – Bozho

+0

所以泛型是全部還是全無?如果您使用原始類型,那麼您將不會獲得該類型的任何泛型,甚至不會依賴於「T」的部分? – Thilo

+2

但是泛型定義中的'MySuperclass ** **'與'Map ** ** myMap'的泛型有什麼共同之處?這些是兩種不同的泛型定義,它們之間沒有「連接」。我不明白。 –

1

這確實是不合理的。這可以被認爲是設計中的一個錯誤。根本原因是決定保持收集的API向後兼容,而不是保持原有的完整並引入新的基因組化API。這個決定在技術上是無稽之談,他們的解釋是可笑的。背後的真正原因可能是Sun不得不推出Java5,但沒有足夠的資源,所以他們採取了簡單的路線(擦除)。所以我們在這裏完全搞砸了。這種混蛋類型系統本身不僅是一個問題,而且也是引入任何新功能的一大障礙。