我读了几篇文章,例如here,但是找不到解决我问题的方法。
为什么我无法添加d?它是对象的子类型...
d的类型:A<B<X>>
List<A<B<? extends Object>>> rv=new LinkedList<>();
rv.add(d); //not working
编辑
我试图简化问题。当我这样做时:
A<B<?>> abcv=new A<B<String>>();
我收到错误消息:类型不匹配:无法从A<B<String>> to A<B<?>>
转换
但是,字符串与“?”兼容-为什么它不起作用?我想将元素添加到列表中,其中最后一种类型可以通过任何方式进行添加,例如:
List<A<B<?>>> rv=new LinkedList<>();
rv.add(new A<B<X>>());
rv.add(new A<B<String>>());
rv.add(new A<B<Integer>>());
答案 0 :(得分:2)
d
的类型应该为A<B<? extends Object>>
或兼容。
答案 1 :(得分:2)
List<SubClaz>
在Java中不是List<SuperClaz>
的子类型。这就是使用通配符的原因:List<SubClaz>
是List<? extends SuperClaz>
的子类型。
现在为您的A<B<?>> abcv=new A<B<String>>();
示例:
通过添加通配符,您使B<String>
成为B<?>
的子类型,但是由于这些也被另一种类型A
包裹,我们回到了第一个问题:
A<B<String>>
不是A<B<?>>
的子类型
(在这种情况下,注意B<?>
是SuperClaz
,B<String>
是SubClaz
。
您可以用相同的方式解决此问题;通过添加另一个通配符:
A<B<String>>()
是A<? extends B<?>>
的子类型。
请记住,这不允许您随意阅读或操作列表。搜索协方差和协方差以获取更多详细信息。这是一个很好的例子:http://bayou.io/draft/Capturing_Wildcards.html
答案 2 :(得分:1)
List<A<B<?>>> rv = new LinkedList<>();
?泛型表示任何类型。
例如:
您可以将任何类型的通用列表分配给List<?>
,但是不能将任何类型的对象添加到列表中,因为编译器由于通配符(?)而不知道它是什么类型
List<?> genericList1 = new ArrayList<String>();
List<?> genericList2 = new ArrayList<Integer>();
List<?> genericList3 = new ArrayList<X>();
/**
* Compiler will allow to assign any type of generic list to List<?>
* but it will not allow to add.
*/
genericList1.add("xyz"); // It will give compiler error
<?>
通配符允许分配ANY类型的列表,但是add()方法在该列表上无效,因为您可能将错误的东西放入集合中。编译器不知道由于通配符(?)而将传递哪种类型。
如果您想将任何类型的对象添加到列表中,都可以像这样获取列表。
List<Object> rv = new LinkedList<>();
rv.add(new A<B<X>>());
rv.add(new A<B<String>>());
rv.add(new A<B<Integer>>());
现在,编译器知道rv是仅接受对象类型的列表,因此编译器不会抱怨任何内容。