关于Java中通配符捕获的困惑

时间:2018-08-15 08:03:32

标签: java generics

我已经阅读了有关通配符捕获如何在Java中工作的文章。 In this section,作者演示了编译器如何捕获通配符类型并进行一些转换。

但是我在编译以下代码后感到困惑(代码本身没有任何意义,我只想测试Java中捕获的通配符)

public class Test {
    public static void main(String[] args) {
    }

    public static void copy(List<?> src, List<?> dest) {
        for (int i = 0; i < dest.size(); i++) {
            dest.set(i, src.get(i));
        }
    }
}

我遇到了编译时错误:

Error:(9, 32) java: incompatible types: java.lang.Object cannot be converted to capture#1 of ?

根据该帖子,编译器应该能够捕获通配符类型src并将其转换为类似List<capture#2>

但是为什么错误提示src.get(i)的类型是Object,而不是capture#2这样的东西?

如果该帖子有误,通配符捕获实际上如何工作?

4 个答案:

答案 0 :(得分:1)

我没有看过链接,但我真的怀疑这与您在此处发布的内容相同...

有效地List<?> src意味着您可以从List检索的唯一内容是Object(除非您知道并可以对其进行强制转换,可能会失败,当然:String s = (String) src.get(0);)。

List<?> dest意味着此目的地实际上是只读,因为?意味着您可以添加任何内容,StringInteger,等等-添加不同类型时会破坏其完整性,因此这是禁止的。

答案 1 :(得分:0)

类型List<?>的参数可以接收任何内容的列表。因此,您可以为List<Integer>输入一个src,为List<String>输入一个dest。然后,您将在出错的行中将Integer添加到String的列表中,这显然是没有意义的。

您可能希望将两个参数限制为相同的列表类型:

public static <T> void copy(List<T> src, List<T> dest) {
    ...
}

答案 2 :(得分:0)

List<?>等效于List<? extends Object>,因为默认情况下,通配符位于Object的上限。

现在,编译器出现错误,因为您无法将任何对象添加到List<?>

为什么?因为您不能保证它真正指向的是哪种列表。它可以是Object的任何子类,因此不能保证在该object中允许使用特定的List。唯一的“保证”是您只能从中读取内容,并且可以获得Object或Object的子类。

答案 3 :(得分:0)

“通配符捕获”意味着您可以将类型List<?>的参数传递给类型List<E>的参数,其中E在该方法中是通用的,并且在{ {1}}。

在这里,您没有任何通用方法,因此捕获并不重要。