GenericWildcard不适用

时间:2013-07-02 08:20:02

标签: java generics

我有一个功能

public static void bar (final List<List<?>> list)
{
}

我可以使用通配符(<?>

进行调用
bar(new ArrayList<List<?>>());

但不是其他类型(例如String

// The method bar(List<List<?>>) in the type Foo is not
// applicable for the arguments (ArrayList<List<String>>)
bar(new ArrayList<List<String>>());

然而,这适用于类似的功能

public static void foo(List<?> l)
{
}

public static void main(String[] args)
{
    // no error
    foo(new ArrayList<String>());
}

你能解释一下,为什么编译器会在第一种情况下抱怨而不是在第二种情况下抱怨?

2 个答案:

答案 0 :(得分:7)

您的问题在这里得到了完美的解释: multiple nested wildcard - arguments not applicable

看看接受的答案。提供的链接应该回答您的所有Java通用问题。

答案 1 :(得分:4)

您应该将您的方法声明为:

private void bar(final List<? extends List<?>> lists) {...}

在这种情况下,呼叫bar(new ArrayList<List<String>>());将起作用。

解释

简而言之:

List<SomeType> - 编译器期望与完全相同类型的呼叫。 List<? extends SomeType> - 编译器期望使用与SomeType兼容(子类)的类进行调用。

在您的情况下定义

void bar (final List<List<?>> list)

将需要一个定义正好为List<List<?>>() nestedList;

的参数

另一方面,当您将方法指定为:

void bar(final List<? extends List<?>> lists)

然后你说你有一个列表,其类型是List<?>的上限,所以ArrayList<String>将是嵌套列表的有效候选者

来自Oracle docs

  

这里有一个很小但非常重要的区别:我们已经取代了   类型列表与列表。现在drawAll()会   接受Shape的任何子类的列表,所以我们现在可以在a上调用它   列出我们是否想要。

     

List是有界通配符的示例。的?   代表一种未知类型,就像我们之前看到的通配符一样。   但是,在这种情况下,我们知道这种未知类型实际上是一种   Shape的子类型。 (注意:它可能是Shape本身,或者是某些子类;   它不需要字面上扩展Shape。)我们说Shape是上层   通配符的界限。