转换为不同于实际类的泛型类型时,没有ClassCastException [英] No ClassCastException when casting to generic type different to actual class
问题描述
我有一些看起来像这样的代码(对方法 get
的否定测试的一部分):
I have some code which looks something like this (part of a negative test of the method get
):
import java.util.*;
public class Test {
Map<String, Object> map = new HashMap<>();
public static void main (String ... args) {
Test test = new Test();
test.put("test", "value"); // Store a String
System.out.println("Test: " + test.get("test", Double.class)); // Retrieve it as a Double
}
public <T> T get(String key, Class<T> clazz) {
return (T) map.get(key);
}
public void put(String key, Object value) {
map.put(key, value);
}
}
我期望它会抛出 ClassCastException
,但它会成功打印:
I was expecting it to throw a ClassCastException
but it runs through successfully printing:
Test: value
为什么不抛出?
推荐答案
在删除类型参数(类型擦除)后,考虑类的外观是有益的:
It is instructive to consider what the class looks like after removing type parameters (type erasure):
public class Test {
Map map = new HashMap();
public static void main (String ... args) {
Test test = new Test();
test.put("test", "value");
System.out.println("Test: " + test.get("test", Double.class));
}
public Object get(String key, Class clazz) {
return map.get(key);
}
public void put(String key, Object value) {
map.put(key, value);
}
}
这将编译并产生与您看到的相同的结果。
This compiles and produces the same result that you see.
棘手的部分是这一行:
System.out.println("Test: " + test.get("test", Double.class));
如果您已这样做:
Double foo = test.get("test", Double.class);
然后在类型擦除后,编译器将插入强制类型转换(因为在类型擦除后 test.get()
返回 Object
):
then after type erasure the compiler would have inserted a cast (because after type erasure test.get()
returns Object
):
Double foo = (Double)test.get("test", Double.class);
类似地,编译器也可以在上述行中插入强制类型转换,如下所示:
So analogously, the compiler could have inserted a cast in the above line too, like this:
System.out.println("Test: " + (Double)test.get("test", Double.class));
但是,它不会插入强制类型转换,因为强制类型转换不需要编译和转换行为正确,因为字符串串联( +
)在所有对象上的工作方式相同;它只需要知道类型是 Object
,而不是特定的子类即可。因此,在这种情况下,编译器可以省略不必要的强制转换。
However, it doesn't insert a cast, because the cast is not necessary for it to compile and behave correctly, since string concatenation (+
) works on all objects the same way; it only needs to know the type is Object
, not a specific subclass. Therefore, the compiler can omit an unnecessary cast and it does in this case.
这篇关于转换为不同于实际类的泛型类型时,没有ClassCastException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!