为什么可以在Java中使用泛型将对象转换为整数?



我找到了一种通过泛型类型将float添加到Integer数组的方法。我很好奇为什么Java在运行时错误中不捕获这个?我试着在文档中查找有关这方面的任何信息,但我没有任何运气。

例如,假设我有两个数组列表,一个包含整数,另一个包含浮点数,如下所示:

ArrayList<Integer> listInt = new ArrayList<>();
ArrayList<Float> listFlt = new ArrayList<>();

listInt.add(6);
listInt.add(71);

listFlt.add(4.92f);
listFlt.add(20.5f);

使用泛型,我可以通过如下方法将float从listFlt复制到listInt:

public static <T extends Number, S extends Number> void copy(ArrayList<T> src, ArrayList<S> dest) {
for (int i = 0; i < src.size(); i++) {
Object x = src.get(i);
dest.set(i, (S)x);
}
}

调用:

ClassName.<Float, Integer>copy(listFlt, listInt);

现在,当我打印listInt时,它显示:

4.92
20.5

当涉及到泛型时,如何可能将对象强制转换为整数?listInt如何存储浮点数?谢谢!

使用泛型,我可以通过如下方法将float从listFlt复制到listInt

注意,在这个方法中,您将转换为类型参数S:

dest.set(i, (S)x);

这将在编译时导致未检查强制转换警告(您不应该忽略!)。

这是允许的,但由于类型擦除,JVM将无法在运行时检查是否允许强制转换。

这是一个堆污染的例子:由于Java语言和类型擦除的规则,您会遇到这样一种情况:您可以将对象添加到错误类型的ArrayList中(在这种情况下:您将Float对象添加到应该包含Integer对象的列表中)。

当您只是打印列表时,没有问题,因为在这种情况下,Java只需要对列表的元素调用toString(),并且该方法对所有对象都存在。

但是当你试图将Integer从列表中取出时,你将得到ClassCastException:

ClassName.<Float, Integer>copy(listFlt, listInt);
Integer i = listInt.get(0); // ClassCastException: Float cannot be cast to Integer

这是Java规则(部分原因是向后兼容性)和Java处理泛型(带有类型擦除)的方式相结合的不幸结果。

记住点:不要忽略"未检查的类型";警告;它们暗示你的代码中可能存在堆污染。

相关内容

  • 没有找到相关文章

最新更新