【问题标题】:Generic types and wildcards in nested lists嵌套列表中的通用类型和通配符
【发布时间】:2017-10-18 16:41:14
【问题描述】:

我正在尝试编写一个将任何列表列表作为参数的方法 - 无论嵌套列表的类型如何。
对于采用任何类型的单个列表的方法,通配符类型可以正常工作(参见示例 1)。但是这个概念并没有扩展到列表列表。从示例 2 中可以看出,该方法只接受 List<List<?>> 类型的参数,但不接受特定类型的参数,例如 List<List<Integer>>。示例 3 使用类型参数 T 并接受 List<List<Integer>> 但不再接受 List<List<?>>。为什么会这样?如何编写一个同时接受List<List<?>>List<List<Integer>> 的方法?

public void test()
{
    List<Integer> list1;
    List<?> list2;
    
    example1(list1); // Valid
    example1(list2); // Valid
    
    List<List<Integer>> listOfLists1;
    List<List<?>> listOfLists2;
    
    example2(listOfLists1); // Error
    example2(listOfLists2); // Valid
    
    example3(listOfLists1); // Valid
    example3(listOfLists2); // Error
}

public void example1(List<?> list) {}

public void example2(List<List<?>> listOfLists) {}

public <T> void example3(List<List<T>> listOfLists) {}

【问题讨论】:

  • This question 稍微讨论了这里的问题。长话短说,你只需要使用List&lt;? extends List&lt;?&gt;&gt; 来代替example2,同样地使用List&lt;? extends List&lt;? extends T&gt;&gt; 来代替example3。泛型真的很挑剔。

标签: java list generics wildcard


【解决方案1】:

example2 不起作用,因为List&lt;List&lt;Integer&gt;&gt; 不是List&lt;List&lt;?&gt;&gt; 的子类型,即使List&lt;Integer&gt;List&lt;?&gt; 的子类型,类似于List&lt;String&gt; 甚至不是List&lt;Object&gt; 的子类型虽然StringObject 的子类型。基本上,当类型不是通过通配符直接参数化时,类型参数必须完全匹配——List&lt;Integer&gt;List&lt;?&gt; 不完全匹配。 (里面有一个通配符,但它是具体类型List&lt;?&gt; 的一部分,而不是顶层的通配符。)

为了能够接受不同的类型参数,它需要在顶层有一个通配符:

public void example4(List<? extends List<?>> listOfLists) {}

【讨论】:

    【解决方案2】:

    这对我有用:

    List<List<Integer>> listOfLists1;
    List<List<?>> listOfLists2;
    
    public TestKlasse() {
        init();
    }
    
    public void init(){
        listOfLists1 = new ArrayList();
        listOfLists2 = new ArrayList();
        listOfLists1.add(Arrays.asList(1,2,3,4,5));
        listOfLists2.add(Arrays.asList("a","a",2,4,"5"));
        test((Collection)listOfLists1);
        test((Collection)listOfLists2);
    }
    
    private void test(Collection<Collection<?>> list){
        list.forEach(e -> {
            System.out.println(e.toString());
        });
    }
    

    结果:

    [1, 2, 3, 4, 5]
    [a, a, 2, 4, 5]
    

    我希望这个解决方案符合您的期望。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-10
      相关资源
      最近更新 更多