我在教学生老式泛型时遇到了一个看不见的东西!我在演讲时的行为! :(
我有一个简单的类
public class ObjectUtility {
public static void main(String[] args) {
System.out.println(castToType(10,new HashMap<Integer,Integer>()));
}
private static <V,T> T castToType(V value, T type){
return (T) value;
}
}
这给出输出 10,没有任何错误!!!我期待这会给我一个 ClassCastException,并出现一些错误,例如 Integer cannot be cast to HashMap。
好奇和愤怒,我在返回值上尝试了 getClass()
,如下所示
System.out.println(castToType(10,new HashMap<Integer,Integer>()).getClass());
如我所料抛出 ClassCastException。
此外,当我将同一个语句分成两部分时,比如
Object o = castToType(10,new HashMap<Integer,Integer>());
System.out.println(o.getClass());
它没有抛出任何错误并打印 class java.lang.Integer
全部用
执行openjdk version "1.7.0_181"
OpenJDK Runtime Environment (Zulu 7.23.0.1-macosx) (build 1.7.0_181-b01)
OpenJDK 64-Bit Server VM (Zulu 7.23.0.1-macosx) (build 24.181-b01, mixed mode)
有人能为我指出正确的方向吗?为什么会发生这种行为?
最佳答案
T
在运行时不存在。它解析为约束的下限。在本例中,没有对象,因此它解析为 Object
。一切都可以转换为 Object
,因此没有类转换异常。
如果你要改变约束条件
private static <V,T extends Map<?,?>> T castToType(V value, T type){
return (T) value;
}
然后对 T
的转换成为对下界 Map
的转换,显然 Integer
不是,你得到类转换您期望的异常。
Also, when I break the same statement into two, something like
Object o = castToType(10,new HashMap<Integer,Integer>()); System.out.println(o.getClass());
It is not throwing any error
castToType(10,new HashMap<Integer,Integer>()).getClass()
这会抛出类转换异常,因为它静态链接到方法 HashMap::getClass
(不是 Object::getClass
),因为签名表示期望 HashMap
作为返回值。这需要对 HashMap
进行隐式转换,但会失败,因为 castToType
在运行时返回一个 Integer
。
当你第一次使用它时
Object o = castToType(10,new HashMap<Integer,Integer>());
您现在静态链接到 Object::getClass
,这很好,不管实际返回的是什么。
“未拆分”版本等同于此
final HashMap<Integer, Integer> map = castToType(10, new HashMap<>());
System.out.println(map.getClass());
这有望证明差异
关于java - 类型转换中的模棱两可的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57853055/