有什么方法可以创建一个通用List,我可以添加一个类型和一个子类型?

时间:2011-01-05 23:35:09

标签: java list generics add

我理解为什么我不能做以下事情:

private class Parent {
};

private class Child extends Parent {
};

private class GrandChild extends Child {
};

public void wontCompile(List<? extends Parent> genericList, Child itemToAdd) {
    genericList.add(itemToAdd);
}

我的问题是有没有实用的方法来设置类型安全列表,你可以在其中调用add(E),其中E已知只有父或子?

我依稀记得使用了一些“|”运算符用于通配符边界,但我在规范中找不到它...

谢谢!

4 个答案:

答案 0 :(得分:0)

没有。

add(E)中,只能在运行时确定E的确切类型。由于子类型关系,声明为Parent类型的任何变量都可以保存对GrandChild对象的引用;没有办法创建一个列表,你不能添加元素类型子类型的对象(至少,编译器会禁止这样的操作)。

真正的问题是:为什么你甚至想要那个?也许你的继承层次结构是颠倒的。

答案 1 :(得分:0)

为什么不呢?您只需要一个满足两个调用参数的List和item参数的匹配泛型类型,您可以非常简单地实现:

import java.util.ArrayList;
import java.util.List;

public class TestClass {

  private class Parent {
  };

  private class Child extends Parent {
  };

  private class GrandChild extends Child {
  };

  public <T extends Parent> void compilesNow(final List<T> genericList, final T itemToAdd) {
    genericList.add(itemToAdd);
  }

  public void addSomeDescendents() {
    final List<Parent> list = new ArrayList<Parent>();
    compilesNow(list, new Parent());
    compilesNow(list, new Child());
    compilesNow(list, new GrandChild());
  }
}

编辑:对不起我错过了关于排除GrandChild的一点......但是,我的例子更进一步说明了如何利用Generics来使这个场景至少编译

答案 2 :(得分:0)

你的类层次结构

public class Parent {

}

public class Child extends Parent {

}

public class GrandChild extends Child {

}

如何将类型及其子类型添加到泛型 List

public class Runner {

    //List that contains anything that has a super class Parent
    private static List<? super Parent> genericList = new ArrayList<>(); 

    public static void main(String[] args) {
        Parent parent = new Parent();
        Child child = new Child();
        GrandChild grandChild = new GrandChild();

        genericList.add(parent);
        genericList.add(child);
        genericList.add(grandChild);

        genericList.forEach(System.out::println);
    }
}

输出

com.abd.test.generics.Parent@1218025c 
com.abd.test.generics.Child@816f27d 
com.abd.test.generics.GrandChild@87aac27

答案 3 :(得分:-1)

您可以在委托给封装的List之前创建一个Facade并执行自己的instanceof检查。

这将是丑陋的,很可能是一个可怕的想法。