时不时地,我觉得我根本不懂 Java.. 我最近发现了 Java 类型转换的这种奇怪行为:
public static void main(String[] args) {
String res = get();
System.out.println(res);
}
public static <T> T get() {
Object longObj = Long.valueOf("0");
T casted = (T) longObj;
System.out.println("longObj=" + longObj.getClass());
System.out.println("casted=" + casted.getClass()); // <-- Why the type of "casted" is Long instead of String???
return casted;
}
输出是:
longObj=class java.lang.Long
casted=class java.lang.Long
Exception in thread "main" java.lang.ClassCastException: java.lang.Long
cannot be cast to java.lang.String
at com.apple.geo.coreloc.Test.main(Test.java:5)
我的困惑是:为什么变量 casted
的类型是 Long
?不应该强制转换为类型T
,即String
吗?
以下是我认为它应该是 String
的原因:
- 在运行时,
String res = get()
提示 get() 方法返回一个 String T casted = (T) longObj;
应该尝试将 Long 类型转换为 String(我希望这里有异常,但没有......)
最佳答案
泛型是编译时检查。它们不是编写糟糕类型转换的保障措施。
你试图做 (String) longIbj;
其中 longObj
很长。那会给你一个运行时 ClassCastException
.
但是,因为它不是 T get()
上下文中的编译时错误T get()
编译正确。由于“类型删除”,T 被提升为最高约束类型。您没有限制类型的上限,因此您的编译器处理的代码大致如下所示:
public static Object get() {
Object longObj = Long.valueOf("0");
Object casted = (Object) longObj;
System.out.println("longObj=" + longObj.getClass());
System.out.println("casted=" + casted.getClass()); // <-- Why the type of "casted" is Long instead of String???
return casted;
}
自 <T>
是一个 Object
填充 longObj
的两行代码和 casted
大致相同。在任何情况下,通过任一名称引用 对对象的多态调用仍将解析为对象的 .getClass()
。方法,它仍然会返回 java.lang.Long
.
Java 中的转换不会创建新对象。如果你想要一个不同的对象,你需要 new
一个不同的对象并用相关信息填充它。在 java 中进行转换只会让您通过转换类型的方法名称访问该类。所以你可能会输 getLong()
在Long
转换为 Object
但它仍然存在(如果您通过 Long
类型的变量调用它。
关于Java泛型类型方法返回错误的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46895118/