2013-03-31 46 views
6

我不明白爲什麼這會讓編譯器感到困惑。我正在使用通用類型T來保存與putget方法無關的對象。我一直認爲GenericClassGenericClass<Object>在功能上是相同的,但我一定會誤會。編譯DoesntWork時,我得到incompatible types - required: String - found: ObjectWorks類做我期望的。這裏發生了什麼?當我不提供泛型類型時,爲什麼這個類的行爲不同?

public class GenericClass<T> { 
    public <V> void put(Class<V> key, V value) { 
     // put into map 
    } 

    public <V> V get(Class<V> key) { 
     // get from map 
     return null; 
    } 

    public static class DoesntWork { 
     public DoesntWork() { 
      GenericClass genericClass = new GenericClass(); 
      String s = genericClass.get(String.class); 
     } 
    } 

    public static class Works { 
     public Works() { 
      GenericClass<Object> genericClass = new GenericClass<Object>(); 
      String s = genericClass.get(String.class); 
     } 
    } 
} 
+0

'genericClass'更接近'genericClass '而不是'genericClass ' –

+0

這就是說,我不明白爲什麼'DoesntWork'不應該工作。 –

+1

試着強制類型:'genericClass。 get(String.class)'(不確定它是否是正確的語法) –

回答

8

有關原始類型是如何工作的事情 - 你已經離開了論據泛型類型 - 是所有仿製藥,他們和他們的方法也被刪除。因此,對於原始GenericClassgetput方法失去其仿製藥。

+0

他們爲什麼會這樣? –

+0

爲了兼容性目的,使用原始類型基本上表明您正在使用傳統的預代理程序代碼;爲了兼容的目的,大多數原始類型的怪異特性都是黑客行爲。 [JLS 4.8](http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.8)有更多詳細信息。 –

+2

但是,爲了說明爲什麼這種特定行爲是必要的,請考慮以下示例:使用Java 1.4構建的舊代碼必須從Java 1.4的「List」 - 預泛型 - 和「List」中獲取相同的行爲Java 5改寫爲引入泛型。它很尷尬,但是向後兼容是必要的 - 但它對於新代碼來說不應該是一個問題,因爲新代碼基本上不會使用原始類型。 –

1

這是因爲當您使用泛型類而沒有額外的類型信息時,您使用的是有時稱爲degenerate類的形式。 degenerate窗體已刪除所有通用類型信息。

本質 - 你的類變成類似:

public class GenericClass { 
    public void put(Class key, Object value) { 
     // put into map 
    } 

    public Object get(Class key) { 
     // get from map 
     return null; 
    } 

    ... 
} 

你所看到的編譯器響應因此預期行爲。

它在Java Puzzlers中提到。

相關問題