【问题标题】:Generics adding subclasses to array泛型将子类添加到数组
【发布时间】:2017-01-21 06:15:37
【问题描述】:

我有一个扩展 A 的类 BA 存储 AItem 列表,B 存储 BItem

列表

在“A”中,我有一个 ArrayList,它使用 [?扩展 AItem] .

我假设这意味着我可以将这个 ArrayList 用于扩展 AItem 的任何类型的对象。

所以在我的 B 类中,我有一个 add(..) 方法,可以将 BItem 添加到项目中。

我认为这会起作用,因为 items arrayList 可以保存从 AItem 扩展的任何对象的列表。

import java.util.ArrayList;

class A {
    public ArrayList<? extends AItem> items;
}

public class B extends A{

    public void add(BItem i) {

        this.items.add(i); //compile error here
    } 
}

//items :
class AItem {}
class BItem extends AItem{}

我该如何让它发挥作用?

我的编译错误如下所示:

类型中的方法add(capture#2-of ? extends AItem) ArrayList 不适用于 参数(BItem)

【问题讨论】:

标签: java generics inheritance


【解决方案1】:

您可能不需要在这里使用泛型。在A 类中拥有AItem 类型的列表应该没问题(我也将它声明为List 类型而不是ArrayList 以获得最佳实践):

class A {
    public List<AItem> items;
}

class B extends A {

    public void add(BItem i) {

        this.items.add(i);
    } 
}

? extends AItem 的问题在于编译器无法保证元素的实际类型是AItemBItem。它可能是另一个子类CItem,在这种情况下,类型安全被破坏。

还有另一种使用泛型设计类层次结构的方法,在该方法中,您在父类中设置类型参数,并在扩展类@中将其设置为适当的子类 (BItem) 987654331@:

class A<T extends AItem> {
    public ArrayList<T> items;
}

class B extends A<BItem>{

    public void add(BItem i) {

        this.items.add(i);
    } 
}

【讨论】:

    【解决方案2】:

    尝试将extends 替换为super

    import java.util.ArrayList;
    
    class A {
        public ArrayList<? super AItem> items;
    }
    
    public class B extends A{
    
        public void add(BItem i) {
    
            this.items.add(i); //compile error here
        } 
    }
    
    //items :
    class AItem {}
    class BItem extends AItem{}
    

    您可以找到有关此行为背后原因的更多详细信息,here

    【讨论】:

      【解决方案3】:

      你可以使用

      public ArrayList<? super AItem> items; 
      

      您现在可以添加到列表中

      但是你做不到

      public class B extends A{
       .....
      
         public BItem getOne(int idx) {
           return this.items.get(idx);
      
         }
      }
      

      jvm 不知道列表中的实际内容。

      你可以生成A类

      class  A<T> {
          public ArrayList<T> items;
      }
      

      然后将你的 B 类定义为

      public class B extends A<BItem>{
      
          public void add(BItem i) {
      
              this.items.add(i); 
          } 
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-04-21
        • 1970-01-01
        • 2019-03-12
        • 2021-11-28
        • 1970-01-01
        • 1970-01-01
        • 2018-05-28
        相关资源
        最近更新 更多