代码之家  ›  专栏  ›  技术社区  ›  user3579222

将对象添加到具有两种类型的泛型列表中

  •  5
  • user3579222  · 技术社区  · 6 年前

    我读了一些帖子,比如 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 回复  |  直到 6 年前
        1
  •  2
  •   oskansavli    6 年前

    List<SubClaz> 不是的子类型 List<SuperClaz> 在Java中。这就是使用通配符的原因: 列出子类 是一个亚型 List<? extends SuperClaz> .

    现在为了你 A<B<?>> abcv=new A<B<String>>(); 例子:

    通过添加通配符,您将 B<String> 亚型 B<?> ,但由于这些也被另一种类型包装 A 我们回到第一个问题:
    A<B<String>> 不是的子类型 A<B<?>>
    (通知) B & lt;?gt; SuperClaz B& lt;String & Gt; SubClaz 在这种情况下)。

    您可以用同样的方法解决这个问题;通过添加另一个通配符:
    A<B<String>>() 是一个亚型 A<? extends B<?>> .

    请记住,这不允许您根据需要读取或操作列表。搜索协方差和逆变以获得更多详细信息。这是一个很好的例子: http://bayou.io/draft/Capturing_Wildcards.html

        2
  •  2
  •   talex    6 年前

    d 应具有类型 A<B<? extends Object>> 或兼容。

        3
  •  1
  •   sagar varsani    6 年前
    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
    

    这个 <?> 通配符允许分配任何类型的列表,但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是只接受对象类型的列表,所以编译器不会抱怨任何事情。

    推荐文章