【问题标题】:How may I add `MyClass` to `List<? extends MyClass>` [duplicate]如何将 `MyClass` 添加到`List<?扩展 MyClass>` [重复]
【发布时间】:2019-02-01 14:03:36
【问题描述】:

我有一个 Java 类,其中包含扩展 MyClass 的对象子项。

class MyClass {
List<? extends MyClass> items;
[...]

由于某种原因,我无法将 MyClass 项插入此列表。我不明白为什么,以及如何绕过这个问题。例如:

void foo(){
  items = new LinkedList<MyClass>(); // This is OK
  items.add(new MyClass()); // Not allowed... why?
}

编译器说“类型 List 中的方法 add(capture#1-of ? extends MyClass) 不适用于参数 (MyClass)”

我真的不明白如何绕过这个问题,以及为什么编译器应该只接受一个必须扩展 MyClass 的类型。

注意:为什么我需要使用这种方法?因为我需要允许 MyClass 的扩展具有子项列表。

【问题讨论】:

  • 为什么第一行是Myclass而不是MyClass
  • 如果您只想将 MyClass 的任何子项的实例添加到项目中,那么 ? extends 位并不是真正需要的:List 将接受 MyClass 类型的任何实例或从 MyClass 继承的任何类...
  • 我认为符号 &lt;? extends MyClass&gt; 被读作“扩展 MyClass 或 MyClass 本身的某个类” - 但该类型中没有足够的信息让编译器知道 which i> 您打算使用的 MyClass 的子类型...

标签: java generics inheritance extends


【解决方案1】:

List&lt;? extends MyClass&gt; items 表示类型参数是未知类型,可分配给MyClass

例如,它可能是MySubClassList

public MySubClass extends MyClass{}

List<? extends MyClass> items = new ArrayList<MySubClass>();

现在考虑您有 MyAnotherSubClass,它也从 MyClass 扩展:

public MyAnotherSubClass extends MyClass{}

MyClass item = new MyAnotherSubClass(); // refer it using MyClass

显然,List&lt;MySubClass&gt; 不应包含MyAnotherSubClass

items.add(item); // compile error

【讨论】:

    【解决方案2】:

    使用extends 只能从集合中获取。你不能投入其中。您可以使用super 做到这一点。

    因此,在您的情况下,如果您使用 -List&lt;? super MyClass&gt; items;,您将不会收到任何编译/运行时错误。

    虽然 super 允许 get 和 put,但 get 时的返回类型是? super T

    【讨论】:

    • 哇!而已!我尝试过的所有其他方法都有其缺点:使用List&lt;? extends MyClass&gt; 我无法添加任何内容。使用List&lt;MyClass&gt; 我需要将所有元素都投射到getter 上,实际上我可以不使用任何setter。这样我只需要在 get 上转换元素,因此,可以写,即List&lt;? super MyClass&gt; _items = getItems(); if (_items == null) _items = new LinkedList&lt;MyClass&gt;(); MyClass item = (MyClass)_items.get(0);items.add(new MyClass()); THANKS。
    • 很高兴为您提供帮助:)
    【解决方案3】:

    声明

    List<? extends MyClass> items;
    

    表示items 是一个List,其类型参数并不完全已知,但它要么是MyClass,要么是一个子类。

    仔细阅读。它解释了为什么将 anything 添加到这样的List 不是类型安全的:它的类型参数是 unknown。如果恰好是MySubClass1,那么添加MyClassMySubClass2 是不正确的。如果恰好是MySubClass2,那么添加MySubClass1 是不正确的。根本没有可以安全添加的类型。

    如果您想要一个List,您可以在其中添加MyClass 类型的对象以及MyClass 的任何子类的对象,那么您可能只是在寻找List&lt;MyClass&gt;

    从技术上讲,List&lt;? super MyClass&gt; 也可以用于该特定目的,但您会遇到相反的问题:假设列表元素是比 Object 更具体的任何类型都是不安全的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多