2013-06-11 69 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