2013-06-11 68 views
0

我有以下代碼:使用Java泛型錯誤

String test = "[{\"color\":\"red\"}]"; 
Class<? extends Base> baseObject = Base.class; 
Collection<? extends Base> elements = new ArrayList<Base>(); 
if (test.startsWith("[")) { 
    elements.addAll(new ObjectMapper().readValue(test, Collection.class)); 
} else { 
    elements.add(new ObjectMapper().readValue(test, baseObject)); 
} 

但是我對

elements.addAll(new ObjectMapper().readValue(test, Collection.class));

得到一個編譯警告:

The expression of type Collection needs unchecked conversion to conform to Collection<? extends capture#1-of ? extends Base> 

elements.add(new ObjectMapper().readValue(test, baseObject));

編譯錯誤:

The method add(capture#2-of ? extends Base) in the type Collection<capture#2-of ? extends Base> is not applicable for the arguments (capture#3-of ? extends Base) 

出什麼問題了?

+0

*什麼*錯誤? –

+1

爲什麼不簡單'收集元素=新的ArrayList ();'? – assylias

+2

'String test =「[{」color「:」red}]「;'< - 我認爲你忘了逃脫引號 –

回答

1

根據Brian的說法,您不能將某些東西添加到通配符類型的集合中(使用super時沒有明確的下界);確實有道理,因爲子類總是可以轉換爲它的超類,但我之前沒有使用超界限的通配符,所以我不太清楚細節)。

http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html

具體做法是:

Since we don't know what the element type of c stands for, we cannot add objects to it. The add() method takes arguments of type E , the element type of the collection. When the actual type parameter is ? , it stands for some unknown type. Any parameter we pass to add would have to be a subtype of this unknown type. Since we don't know what type that is, we cannot pass anything in. The sole exception is null , which is a member of every type.

類型擦除是...好了,你知道的。

+1

不完全。您可以添加東西到使用「超級」的集合,例如你可以將任何'InputStream'的子類添加到'Collection <?超級InputStream>' – Brian

+0

打我:) – LexLythius

+0

我仍然得到一個編譯警告elements.addAll(新的ObjectMapper()。readValue(jsonRep,Collection.class)); – Dejell

2

錯誤可以很容易地解釋。您的集合被定義爲擁有延伸爲Base的類的實例。 ObjectMapper.readValue被定義爲以下:

public <T> T readValue(JsonParser jp, Class<T> valueType)

這意味着,它返回指定爲第二個參數類的實例。如果第二個參數是Collection.class,則此方法返回Collection。只需Collection,而不是Collection<? extends Base>而不是Collection<Base>。所以,java編譯器不能確定你打算將包含正確對象的集合放入定義爲Collection<? extends Base>elements。此外,java語法不允許提供帶泛型的參數類,即不能調用readValue(c, Collection<Base>.class)

第二種情況比較複雜。 baseObject定義爲Class<? extends Base>elements集合也被定義爲Class<? extends Base>。所以有什麼問題。問題出在?。問號意味着「延伸基地的東西」。但是在這兩種情況下,這兩種不同的「東西」。

該解決方案可收集的任何變化定義Class<Base>,或者使用在兩種情況下,一個類或方法的通用參數,如:

public <T extends Base> myMethod() { 
    Class<T> baseObject = Base.class; 
    Collection<T> elements = new ArrayList<T>(); 
    elements.add(new ObjectMapper().readValue(test, baseObject)); 
} 

現在無論baseObjectelements使用相同類型的T確實延伸Base