我试图理解泛型,但我阻止了通配符边界和强制转换。例如:
List<? extends Number> l = new ArrayList<>();
List<PositiveInteger> p = new ArrayList<PositiveInteger>();
p.add(new PositiveInteger(10));
l = p;
NegativeInteger ni = (NegativeInteger) l.get(0);// runtime java.lang.ClassCastException:
System.out.println(ni);
NegativeNumber和PositiveNumber都扩展了Number。所以问题是为什么在将列表中的元素转换为NegativeNumber时编译时没有警告?有没有办法防止这种类型的异常?
答案 0 :(得分:0)
使用通配符(如<? extends Number>
)定义Generic类型时,不应将对象强制转换为Number的子类,因为泛型类型表示您将获得Number
的子类实例。与此代码块相似:
Number n = new PositiveInteger(10);
NegativeInteger ni = (NegativeInteger ) n;
答案 1 :(得分:0)
一旦你投射,你告诉编译器“我知道我在做什么”,所以只要可以投射对象(NegativeNumber extends Number - &gt; ok)它就不会抱怨。
如果你真的需要强制转换(你想要避免;泛型是关于编译时安全性并避免“不安全”的强制转换),你可以先检查它:
Number number = l.get(0);
if (number instanceof NegativeInteger){
NegativeInteger ni = (NegativeInteger) l.get(0);
...
}
答案 2 :(得分:0)
Object a;
Integer b = new Integer(5);
a=b
Double c = (Double)a;
发生ClassCastException,因为您正在尝试将类转换为另一个不是父类/子类的类
关于防止它的问题:
编译器在运行时不知道l
中的内容。但您可以使用List<PositiveInteger>
而不是通配符来告诉编译器l
中的内容。如果必须使用List<? extends Number>
,则可以创建一个尝试强制转换对象的方法,这样就可以判断对象是List<PositiveInteger>
还是List<NegativeInteger>
,如here:< / p>
if(l instanceof List<NegativeInteger>){
//Do something
}
所以如果我相应地更改你的代码:
List<? extends Number> l = new ArrayList<>();
List<PositiveInteger> p = new ArrayList<PositiveInteger>();
p.add(new PositiveInteger(10));
l = p;
Object ni = l.get(0);
if(ni instanceof NegativeInteger){
NegativeInteger tmp = (NegativeInteger)ni;
System.out.println(ni);
}