使用两种类型将对象添加到通用列表

时间:2019-01-02 09:57:45

标签: java generics

我读了几篇文章,例如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>>());

3 个答案:

答案 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<?>SuperClazB<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是仅接受对象类型的列表,因此编译器不会抱怨任何内容。