【问题标题】:Add to generic List<?> produce compilation error添加到泛型 List<?> 产生编译错误
【发布时间】:2017-12-19 14:34:09
【问题描述】:

以下应用程序在 (*) 行产生编译错误

ArrayList<?> l = new ArrayList<>();        
l.add(new Integer(1));

编译错误说:

error: no suitable method found for add(C<CAP#1>)
    l.add(o);

这是为什么呢?我认为 List 应该接受任何东西

【问题讨论】:

标签: java generics compiler-errors


【解决方案1】:

您误解了List&lt;?&gt; 的含义。

它确实不是意味着:任何类型的对象的List,因此您应该能够向List添加任何东西(它与原始@987654324不同@ 或 List&lt;Object&gt;)。

意思是:List,属于特定但未知的类型。因为类型是未知的,所以你不能在列表中添加任何东西 - 编译器不知道列表中对象的确切类型应该是什么,所以它无法检查你是否没有尝试将某些东西放入列表中不应该被允许,所以它不允许你添加任何东西到列表中。

【讨论】:

  • 为什么下面的代码有效: public static class C {} ; ArrayList> l = new ArrayList(); C> o = 新 C(); l.add(o);
  • 因为这是一个泛化的类,类型可以被编译器推断出来
【解决方案2】:

我通常不喜欢使用通配符。这些是选项:

使用列表是针对未知类型的列表:

List<?> list = Arrays.asList(1, 2d, "3"); // can contain any Object
for (Object obj : list) { // you can retrieve them
    System.out.println("--> " + obj);
}
list.add("a"); // compile error

使用&lt;? extends Number&gt; 可让您从列表中检索数字,但您仍然无法添加任何内容:

List<? extends Number> list2 = Arrays.asList(1, 2, 3); // can contain any number
for (Number n : list2) {
    System.out.println("--> " + n);
}
list2.add(5); // compile error

List<? extends Number> list3 = Arrays.asList(1, 2d, 3F); // can contain any number
for (Number n : list3) {
    System.out.println("--> " + n);
}
list3.add(5); // compile error

&lt;? extends ...&gt; 的反义词是&lt;? super ...&gt;。这看起来很奇怪。关键是这样的List&lt;&gt; 的调用者可以添加适当类型的东西。检索是一个问题:

List<? super Integer> list4 = new ArrayList<>();
list4.add(1);
for (Integer num : list4) { } // compile error
for (Object num : list4) { }  // this is fine, but not that useful

如果你想要一个灵活的数据结构,你可以使用正确的超类型。例如,List&lt;Number&gt; 非常灵活。如果你真的需要,你可以使用像List&lt;T extends Number&gt; 这样的绑定类型。您可以在this answer 阅读更多相关信息。

【讨论】:

    猜你喜欢
    • 2014-11-19
    • 2021-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多