2016-01-22 36 views
5

我正在嘗試學習Java泛型,並找到以下代碼。當調用print(列表<T> a,T b)與不同的T類時發生錯誤

public static <T> void print(T a, T b){ 
    System.out.println(a); 
    System.out.println(b); 
} 

public static void main(String[] args){ 
    print(new ArrayList<String>(), 1); 
} 

這可以毫無問題地工作。

但是,當我將print方法更改爲以下時,它會給我編譯錯誤。

public static <T> void print(List<T> a, T b){ 
    System.out.println(a); 
    System.out.println(b); 
} 

錯誤:

GenericTest.java:9: error: method print in class GenericTest cannot be applied to given types; 
    print(new ArrayList<String>(), 1); 
    ^
    required: List<T>,T 
    found: ArrayList<String>,int 
    reason: no instance(s) of type variable(s) T exist so that argument type int conforms to formal parameter type T 
    where T is a type-variable: 
    T extends Object declared in method <T>print(List<T>,T) 
1 error 

誰能幫助我理解錯誤?

回答

8

的超類型,你應該瞭解的第一件事是,有以下方法簽名

public static <T> void print(T a, T b) 

兩個T必須是相同的類型,也就是說ab將具有相同的傳染類型。

那麼爲什麼它爲new ArrayList<String>()1?因爲這兩個參數實際上可以表示爲Serializable,這是最近的公用超類型的ArrayListInteger

  • ArrayList實現Serializable接口。
  • 1可以裝入Integer,這也是Serializable

所以在這種情況下,編譯器會推斷TSerializable


在第二種情況下,與簽名

public static <T> void print(List<T> a, T b) 

沒有共同的超類型T這將是有效的兩個List<String>Integer。誠然,StringInteger都是Serializable,但自generics aren't polymorphic,它不起作用。

+0

你能不能也解釋了爲什麼它解析爲'Serializable'而不是任何其他公用的超類型? – Codebender

+0

@Codebender因爲它是'ArrayList'和'Integer'之間最近常見的超類型。 「對象」將是層次結構中的一個層次。 – Tunaki

+0

我不明白接口和類之間如何形成層次結構(我會問一個關於這個問題的新問題),但eclipse顯示它已解析爲可序列化(+1)... – Codebender

5

編輯:它沒有得到解決對象,因爲我已經提到,但對Serializable。 See Tunaki's correct answer for the reason

在您的第一個案例中,T已解析爲最具體的類型,它可以引用您的兩個參數。

而且在你的榜樣,它會被解析爲 Object Serializable,因爲ArrayListInteger都是 Object Serializable子類型。

但在你的第二個例子,你有一個List<T>作爲參數...

現在,當你與ArrayList<String>調用它,類型T被解析爲String。它解決不了任何其他類型的,因爲 ArrayList<Object> ArrayList<Serializable>ArrayList<String>

3

你調用該方法在以下幾個方面:

print(new ArrayList<String>(), "SimpleString"); 

print(new ArrayList<Integer>(),5) 

因爲<T>是一個類型,它不能是字符串和整數在同一時間。

,如果你做這樣的事您的電話可以工作:

public static <T, K> void print(List<T> a, K b){ 
    System.out.println(a); 
    System.out.println(b); 
} 

public static void main(String[] args){ 
    print(new ArrayList<String>(),1); 
} 
+0

這是最好的答案,因爲它是唯一一個擁有2個類型參數的代碼。由於語法對初學者來說不一定很直觀。該示例闡明瞭如何使用它。工作很好。將+1明天(投票限制)。 – HopefullyHelpful

相關問題