【问题标题】:<? extends > Java syntax<?扩展 > Java 语法
【发布时间】:2013-04-03 10:10:33
【问题描述】:

这段代码:

List<? extends Reader> weirdList;
weirdList.add(new BufferedReader(null));

有一个编译错误

类型中的方法add(capture#1-of ? extends Reader) 列表不适用于 参数(BufferedReader)

为什么? BufferedReader 扩展了 reader,那为什么不是“匹配”呢?

【问题讨论】:

标签: java generics


【解决方案1】:

List&lt;? extends Reader&gt; weirdList 可以保存对任何类型的List 的引用,该引用存储了任何类型的Reader。所以有可能

List<? extends Reader> weirdList1 = new ArrayList<BufferedReader>();
List<? extends Reader> weirdList2 = new ArrayList<FileReader>();

如果 Java 允许您将 BufferedReader 添加到 weirdList1,它还必须允许您将 BufferedReader 添加到 weirdList2(引用类型相同),因为 weirdList2 应该不会发生这种情况仅存储 FileReaders。

【讨论】:

    【解决方案2】:

    当编译器看到&lt;? extends Reader&gt; 时,它会假定它可能是任何 类型,它是Reader 或扩展了Reader。它可能是与BufferedReader 不兼容的东西,例如StringReader。因此,如果类定义中的泛型类型出现在诸如add 之类的方法的参数中,并且实例的类型具有诸如&lt;? extends Something&gt; 之类的东西,则出于类型安全原因,编译器必须禁止它。在这个例子中,它可能List&lt;StringReader&gt;,所以你不能在这里添加BufferedReader

    【讨论】:

      【解决方案3】:

      对于你给的变量:

      List<? extends Reader> weirdList;
      

      以下所有分配都是有效的:

      weirdList = new ArrayList<Reader>();
      weirdList = new ArrayList<FileReader>();
      weirdList = new ArrayList<BufferedReader>();
      weirdList = new ArrayList<InputStreamReader>();
      

      希望这可以解释您的编译错误。如果weirdList 拥有ArrayList&lt;BufferedReader&gt; 类型的值,那么您正在尝试的操作是有意义的,但对于ArrayList&lt;FileReader&gt; 类型的值则没有意义。由于List&lt;? extends Reader&gt; 类型的变量可以保存任一类型的值(以及更多!),Java 将其称为错误。

      Java 中的泛型很难理解。您可以认为List&lt;? extends Reader&gt; 类型对于方法中的赋值或参数类型最有用,因此它们可以接受多种类型。对于“常规使用”,您可能最好使用像 List&lt;Reader&gt; 甚至 List&lt;BufferedReader&gt; 这样的“裸”泛型。

      【讨论】:

        猜你喜欢
        • 2017-09-14
        • 2014-03-28
        • 2014-01-15
        • 2020-03-12
        • 2020-02-24
        • 2019-07-24
        • 2019-04-16
        相关资源
        最近更新 更多