【问题标题】:Confusion about wildcards capture in Java关于Java中通配符捕获的困惑
【发布时间】:2018-08-15 08:03:31
【问题描述】:

我读过一篇关于通配符捕获如何在 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&lt;capture#2&gt;之类的东西

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

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

【问题讨论】:

  • 在我的eclipse中,错误信息是The method set(int, capture#2-of ?) in the type List&lt;capture#2-of ?&gt; is not applicable for the arguments (int, capture#3-of ?)
  • @AshishSingh 我使用javac 命令编译该文件,上面写着Object cannot be converted to CAP#1

标签: java generics


【解决方案1】:

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

实际上List&lt;?&gt; src 意味着您可以从List 中检索到的唯一内容是Object(除非您知道类型并且可以转换它,当然这可能会失败: String s = (String) src.get(0);)。

List&lt;?&gt; dest 表示此目的地实际上是只读,因为? 表示您可以添加任何内容,StringInteger 等 - 您将破坏它的完整性添加不同的类型,因此这是被禁止的。

【讨论】:

    【解决方案2】:

    List&lt;?&gt; 类型的参数可以接收任何内容的列表。因此,您可以为src 传递一个List&lt;Integer&gt;,为dest 传递一个List&lt;String&gt;。然后,您将在出现错误的行中将 Integer 添加到 String 列表中,这显然没有意义。

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

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

    【讨论】:

      【解决方案3】:

      List&lt;?&gt; 等价于List&lt;? extends Object&gt;,因为默认情况下,通配符的上限为Object

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

      为什么?因为你无法保证它真正指向的是哪种 List。它可以是Object 的任何子类,因此您不能保证在该List 中允许特定的object。唯一的“保证”是你只能从中读取,你会得到一个 Object 或 Object 的子类。

      【讨论】:

        【解决方案4】:

        “通配符捕获”意味着您可以将List&lt;?&gt; 类型的参数传递给List&lt;E&gt; 类型的参数,其中E 在该方法中是通用的,并且仅在&lt;E&gt; void foo(List&lt;E&gt; something) 等参数中使用一次。

        在这里,您没有任何通用方法,因此捕获无关紧要。

        【讨论】:

          猜你喜欢
          • 2016-08-02
          • 1970-01-01
          • 2020-09-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-04-10
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多