为什么可以在 Java 中使用泛型将对象转换为整数?
Why can an Object be cast as an Integer using generics in Java?
我找到了一种通过泛型将浮点数添加到整数数组的方法。我很好奇为什么 Java 没有在运行时错误中捕捉到这个?我试图通过文档查看有关此的任何信息,但我没有任何运气。
例如,假设我有两个 ArrayList,一个包含整数,一个包含浮点数,如下所示:
ArrayList<Integer> listInt = new ArrayList<>();
ArrayList<Float> listFlt = new ArrayList<>();
listInt.add(6);
listInt.add(71);
listFlt.add(4.92f);
listFlt.add(20.5f);
使用泛型,我可以通过如下方法将 listFlt 中的 Floats 复制到 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 如何存储 Floats?谢谢!
Using generics, I can copy the Floats from listFlt into listInt through a method like this
请注意,在此方法中,您正在转换为类型参数 S
:
dest.set(i, (S)x);
这将在您编译它时导致未经检查的转换警告(您不应忽略!)。
允许,但由于类型擦除,JVM 将无法在运行时检查是否允许转换。
这是 heap pollution 的一个示例:由于 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 与泛型一起工作的方式(类型擦除) ).
要记住:不要忽略“unchecked cast”警告;它们暗示您的代码中可能存在堆污染。
我找到了一种通过泛型将浮点数添加到整数数组的方法。我很好奇为什么 Java 没有在运行时错误中捕捉到这个?我试图通过文档查看有关此的任何信息,但我没有任何运气。
例如,假设我有两个 ArrayList,一个包含整数,一个包含浮点数,如下所示:
ArrayList<Integer> listInt = new ArrayList<>();
ArrayList<Float> listFlt = new ArrayList<>();
listInt.add(6);
listInt.add(71);
listFlt.add(4.92f);
listFlt.add(20.5f);
使用泛型,我可以通过如下方法将 listFlt 中的 Floats 复制到 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 如何存储 Floats?谢谢!
Using generics, I can copy the Floats from listFlt into listInt through a method like this
请注意,在此方法中,您正在转换为类型参数 S
:
dest.set(i, (S)x);
这将在您编译它时导致未经检查的转换警告(您不应忽略!)。
允许,但由于类型擦除,JVM 将无法在运行时检查是否允许转换。
这是 heap pollution 的一个示例:由于 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 与泛型一起工作的方式(类型擦除) ).
要记住:不要忽略“unchecked cast”警告;它们暗示您的代码中可能存在堆污染。