[英]Generics and parameterized types in Java
以下代码导致编译时错误:
类型List中的方法add(capture#1-of?extends Object)不适用于参数(String)
代码:
List<? extends Object> a1 = new ArrayList();
a1.add("string");
错误在线:
a1.add("string");
由于类String从Object扩展,为什么ref a1不接受String类型?
? extends Object
? extends Object
表示“一些未知类型X
延伸Object
”。 通过尝试向集合添加String
,您实际上声称X = String
,编译器无法验证。 就编译器而言, X
也可以是Integer
或完全不同的东西。
换句话说List<? extends Object>
List<? extends Object>
并不意味着“任何扩展Object
东西”。 一个简单的List<Object>
意味着。
我建议阅读这篇文章, http://java.dzone.com/articles/covariance-and-contravariance 。 (斜体添加是我的)
总之,我们使用协方差
<? extends Object>
当我们只打算从结构中取出泛型值时,<? extends Object>
。 我们使用逆变<? super Object>
<? super Object>
当我们只打算将泛型值放入一个结构中时,当我们打算同时执行这两个操作时,我们使用一个不变的<Object>
。
您将列表定义为持有协变对象类型,这意味着您可以编写Object o = a1.get(1)
但不能编写a1.add("foo")
。 如果你想能够添加对象而不是让它们回来,那么你需要像这样定义你的列表:
List<? super Object> a1 = new ArrayList<>();
这有点不幸,在我看来,语言作者使用术语extend
和super
来表示协方差和逆变,特别是在上面的例子中,因为没有超类型的Object
。
List<? extends Object>
List<? extends Object>
可用于每种类型的列表。
您如何看待,例如,让它添加任何对象是否安全?
List<? extends Object> a1 = new ArrayList<Integer>();
a1.add("string");
只有安全值才能为null
因为它不属于任何特定类型。
要解决此问题,您可以使用例如List<String> a1 = new ArrayList<String>()
或List a1 = new ArrayList()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.