2014-01-22 41 views
2

我想學習java泛型。我寫了一個方法:爲什麼調用不同類型的泛型方法會導致編譯錯誤?

public <T> T Gmethod(T a,Collection<T> list){ 
     return a;} 

雖然調用這個與Gmethod("A",list);是好的,其中的列表是Object類型,

但稱這是與Gmethod(new Object(),list);其中列表是String類型是錯誤, 爲什麼呢?

+0

您正在試圖通過兩種不同的類型,所以這類型你想成爲的T參數? – solvator

回答

4

具有

<T> T method(T a, Collection<T> list) { return a; } 

並用

Collection<Object> list = new LinkedList<>(); 
method("A", list); 

調用它會導致編譯器推斷出類型Object的類型變量T,如listCollection<Object>類型。變量a的類型是String,它是Object的子類型。所以這個方法調用是允許的。

調用帶

Collection<String> list = new LinkedList<>(); 
method(new Object(), list); 

該方法將再次導致編譯器推斷該類型變量T類型對象,如現在aObject類型。因此,編譯器請求參數list的參數爲Collection<Object>(或子類型)類型。 Collection<String>不是Collection<Object>的子類型。所以編譯器不允許這個方法調用。

+0

絕對正確的仿製藥難倒「<...>但集合不收集<...>的亞型。」 +1 – solvator

2

當你有一個參考T實際的類可以是T或一個子類。當你有一個<T>它必須是那個類,只有那個類。這是必需的,因爲它是引用的容器,並且修改此容器可以更改原始容器。這不會在簡單參考中發生,因爲它是作爲副本傳遞的。

引用是按值複製的。

String a = "hi"; 
Object b = a; 
b = new Object(); // no problem as `a` is not changed by this. 

但是對於容器來說,這不能很好地工作,因爲只有容器的引用被複制,而不是容器本身。

List<String> a = new ArrayList<>(); 
a.add("hi"); 
List<Object> b = (List) a; // compiler warning. 
b.add(new Object());  // alters `a` in an incorrect way. 
a.get(1);     // ClassCastException oops. 
+0

請您詳細說明一下。 –

+0

@NarendraPathai希望更清楚。 –

+0

+1是的我現在明白了。我也提供了我的理解視角。你能否也請通過我的答案來驗證我的理解。我會很感激。謝謝。每一個新的一天,說這個我得到某種方式:( –

1

正如@Seelenvirtuose和@Peter Lawrey在他們的回答中所建議的那樣,這是編譯器爲您做的Type Inference。

要測試的編譯器結合Object第一個電話試試這個,

class Main{ 

    public static void main(String[] args){ 
      Collection<Object> listOfObject = new ArrayList<>(); 
      Main.<String>method("a",listOfObject); //compile time error here 
    } 

    public static <T> T Gmethod(T a, Collection<T> coll){ 
     return a; 
    } 
} 
+0

你說,「集合不能包含的對象」。雖然這是真的,但並不是問題!事實上,問題是:編譯器要求所有參數是相同類型或方法參數的子類型,並且它不是Collection 的子類型。 String和Object之間的子類型關係並不重要! – Seelenvirtuose

+0

@Seelenvirtuose'編譯器請求所有參數爲相同類型或方法參數的子類型.'是子類型還是超類型?首先選擇超類型。我誤解了嗎? –

+0

在這兩種方法調用中,編譯器推斷爲T的類型爲Object(首先,這是因爲_list_的類型爲Collection ,其次是因爲_a_的類型爲Object。所以這個方法的簽名 - 對於這兩個調用 - 都是'Object method(Object a,Collection list)'。使用實際參數調用此方法會強制_a_的參數具有Object或subtype(可以是任何類型)的類型,並且強制_list_的參數的類型爲Collection 或子類型。但是Collection 不是Collection 的子類型。順便說一下,名單將是這樣一個亞型。 – Seelenvirtuose

相關問題