GenericWildcard不适用

Mic*_*ann 9 java generics

我有一个功能

public static void bar (final List<List<?>> list)
{
}
Run Code Online (Sandbox Code Playgroud)

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

bar(new ArrayList<List<?>>());
Run Code Online (Sandbox Code Playgroud)

但不是与其他类型(例如String)

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

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

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

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

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

Mat*_*yas 4

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

private void bar(final List<? extends List<?>> lists) {...}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,调用bar(new ArrayList<List<String>>());就可以了。

说明

简而言之:

List<SomeType>- 编译器将期望调用具有完全相同的类型。 List<? extends SomeType>- 编译器将期望调用与 . 兼容的类(子类)SomeType

在你的情况下定义

void bar (final List<List<?>> list)
Run Code Online (Sandbox Code Playgroud)

将期望一个参数的定义恰好是List<List<?>>() nestedList;

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

void bar(final List<? extends List<?>> lists)
Run Code Online (Sandbox Code Playgroud)

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

来自Oracle 文档

这里有一个很小但非常重要的区别:我们用 List 替换了类型 List。现在,drawAll() 将接受任何 Shape 子类的列表,因此如果需要,我们现在可以在 List 上调用它。

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

  • 问题不是他应该怎么做,而是为什么它不起作用! (4认同)