2013-04-16 34 views
2

例子:誤區類返回實例從Java中的子類的實例稱爲類的通用方法

interface S {} 

interface SS extends S {} 

abstract class A<T extends S> { 
    T get() {…} 
} 

abstract class B<BT extends SS> extends A<BT> {} 

爲什麼((B)someInstanceOfB).get()返回S類型的對象(我們應該把它轉換爲手動SS)時,編譯器可以確定返回的對象至少是SS

編譯器爲什麼不讓隱式類轉換爲更清晰的代碼?代碼版本爲1.5+,這對編譯器來說不是祕密。 (解決)

更新:爲什麼不編譯器來編譯B類,因爲它隱含有方法BT get() { return super.get(); }

這個問題在Java 1.7+中解決了嗎?

+0

我不明白這個問題。但'S'和'SS'是這裏的接口。 – midhunhk

+0

@silverback修改後的問題。接口有什麼問題? –

回答

4

通過鑄造到B您正在使用a raw type

使用原始類型從對象中刪除所有通用信息,不管它在哪裏。

這意味着,對於在原始類型Bget方法看起來像它返回一個S(因爲這是類型參數T的擦除(即,在運行時使用的實際類型))。

爲了避免這種情況,從來沒有使用原始類型!它們專門用於向後兼容和與遺留代碼交互。

改爲鑄造成B<? extends SS>

否:在將來的Java版本中,這個問題可能永遠不會「解決」,因爲在正確使用泛型時它不存在。

關於更新:否,B確實不是有一個方法BT get()。它有一個方法T get()其中T綁定到類型參數BT,它有一個下限SS。但由於所有通用類型信息在使用原始類型時被丟棄,因此T仍然回退到原始刪除,即S

規則很簡單,基本上說「當你使用原始類型時,它就好像類一樣沒有泛型」。然而,這種影響並不總是很明顯,就像在這種情況下一樣。

+0

我幫你。它是爲了編譯類的向後兼容性而製作的:可以使用帶有過時代碼和編譯器的新版本的編譯代碼。 –

+0

問題更新 –

+0

關於問題更新的一些想法。這是一個修辭問題。我明白,直到我提出的編譯器邏輯沒有在1.5v編譯器中實現(由標準定義),它將永遠不會實現。至於我,投到'B <?擴展了SS>'破壞了代碼的審美性,並且我一直傾向於編譯類中的更多字節(由我提出的隱式方法)。 –

1

您沒有參數化您的B實例。

比方說,你有實現SSC

然後,new B<C>().get();將返回C類型的對象。

new B().get();行上,您的IDE必須告訴您「B是原始類型,對泛型類型B的引用應該被參數化。

+0

對不起,我犯了一個錯誤...我更新了問題。 –

+1

@Errandir問題依然存在:使用'(B)someInstanceOfB',您不參數化'B'。你必須至少使用'(B )someInstanceOfB'或者'(B )someInstanceOfB'('get'然後返回'Object')。 – sp00m

+0

你的論證有問題。代碼塊'S s =((B)someInstanceOfB).get()'和'S s =((A)someInstanceOfA).get()'可以正常工作。 –

相關問題