我理解为什么我不能做以下事情:
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已知只有父或子?
我依稀记得使用了一些“|”运算符用于通配符边界,但我在规范中找不到它...
谢谢!
答案 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检查。
这将是丑陋的,很可能是一个可怕的想法。