我有这种情况,但为什么java不尊重类层次结构?
import ...
public class GenericsTest {
public static void main(String[] args) {
List<Integer> myList = new ArrayList<Integer>();
myList.add(1);
myList.add(new Integer(2));
new GenericsTest().doInsert(myList);
}
private void doInsert(List<? extends Number> myList) { // Number <- Integer
myList.add(new Integer(1)); // This don't compiles
}
}
有人可以解释一下吗? 感谢!!!
答案 0 :(得分:2)
泛型中的通配符并不意味着“任何”意味着“我不知道”。所以List<? extends Number>
不是“一个可以容纳任何扩展数字的列表”。它是“一个扩展数量的东西的列表,但我不知道它们是什么。”因此,向它添加一个Integer是违法的,因为你不知道Integer是否是扩展数字的东西,这是一个列表。任何扩展数字的列表都只是List<Number>
。
答案 1 :(得分:1)
想象一下,如果您提供的代码合法,下列代码会发生什么:
List<Double> listDouble = new ArrayList<Double>();
doInsert(listDouble);
Double d = listDouble.get(0); //ClassCastException!
编译器在最后一行添加隐式转换。此转换在运行时失败,这打破了泛型的类型安全保证,因为编译器不会使您免于破坏列表内容和数据类型假设。它应该只包含Double值,但是整数内部找到了一个整数。
您的选择:
doInsert(List<? extends Number> myList)
允许迭代Numbers,但不允许添加到集合。接受在Number。的任何子类型上定义的列表。
doInsert(List<Number> myList)
允许迭代和修改,但只接受与List&lt; Number&gt;完全相同的列表。
doInsert(List<? super Number> myList)
允许迭代项目(作为对象),并允许添加任何类型的数字。只接受其祖先数量的列表(在这种情况下,它实际上是无用的)。
答案 2 :(得分:0)
这不起作用的原因是因为引用List的类型不必是整数。但是,以下将编译。
private void doInsert(List<Number> myList) {
myList.add(new Integer(1));
}
同时:
private void doInsert(List<? extends Number> myList) {
((List<Number>)myList).add(new Integer(1));
}
我根据@Eyal Schneider的评论附上了这个答案,表明如果你正确设置它,列出的第二种方法是有效的。虽然这很可能不是一件好事。
public class Test{
public void doInsert(List<? extends Number> myList) {
((List<Number>)myList).add(new Integer(1));
((List<Number>)myList).add(new Short("2"));
((List<Number>)myList).add(new BigDecimal("3"));
...
}
public static void main(String[] args){
Test t=new Test();
List<Number> list=new ArrayList<Number>();
t.doInsert(list);
for(Number number:list)
System.out.println(number);
}
}
答案 3 :(得分:0)
考虑以下反例,假设它是可以接受的:
public class GenericsTest {
public static void main(String[] args) {
List<Integer> myList = new ArrayList<Integer>();
myList.add(1);
myList.add(new Integer(2));
List<Integer> myDoubleList = new ArrayList<Double>();
myList.add(1.0);
myList.add(new Double(2));
new GenericsTest().doInsert(myList); // Here you're trying to add an Integer into a List<Double>
}
private void doInsert(List<? extends Number> myList) { // Number <- Integer
myList.add(new Integer(1)); // This don't compiles
}
}