对泛型参数类型的错误转换不会在Java中引发ClassCastException [英] A bad casting to Generics parameter type does not throw ClassCastException in Java
问题描述
所以,我有一个比较深奥的问题。我正在尝试创建一个有点通用但类型化的属性收集系统。它依赖于似乎是错误的核心假设。该代码说明了这个问题:
So, I have rather esoteric question. I'm trying to create a somewhat generic, but typed property collection system. It's reliant on a core assumption that seems to be erroneous. The code illustrates the issue:
import java.lang.Integer;
public class Test {
private static Object mObj = new String("This should print");
public static void main(String[] args ) {
String s = Test.<String>get();
System.out.println(s);
try {
// actual ClassCastException reported HERE
int i = Test.<Integer>get();
} catch ( ClassCastException e ) {
System.out.println("Why isn't the exception caught earlier?");
}
int i2 = getInt();
}
public static <T> T get() {
T thing = null;
try {
// Expected ClassCastException here
thing = (T)mObj;
} catch ( ClassCastException e ) {
System.out.println("This will *not* be printed");
}
return thing;
}
// This added in the edit
public static Integer getInt() {
return (Integer)mObj;
}
}
在编译并运行输出后,
This should print
Why isn't the exception caught earlier?
在静态方法 get中,我尝试转换为通用参数类型T。基础成员(mObj)是String类型的。在第一次调用中,Generic参数为兼容类型,因此应用程序将适当地打印字符串。
In the static method "get", I'm attempting to cast to the generic parameter type T. The underlying member (mObj) is of String type. In the first invocation, the Generic parameter is of compatible type, so the app prints the string appropriately.
在第二次调用中,Generic参数的类型为Integer。因此,get方法中的强制转换应失败。而且我希望它会引发ClassCastException(打印语句这将*不*将被打印。)但这不是发生的情况。
In the second invocation, the Generic parameter is of type Integer. Thus, the cast in the get method should fail. And I would hope it would throw a ClassCastException (printing the statement "This will *not* be printed".) But this isn't what happens.
相反,在尝试将返回值分配给变量 i时,之后引发强制转换异常。这里的问题是:
Instead, the casting exception is thrown after the get method returns when the returned value is attempted to be assigned to the variable "i". Here's the question:
此延误转换错误的解释是什么?
What is the explanation for this delayed casting error?
**编辑**
为了乐趣和完整性,我添加了一个非通用的getInt方法来说明我希望获得的响应。
** EDIT ** For the sake of fun and completeness, I added a non-generic getInt method to illustrate the response I was hoping to get. Amazing what happens when the compiler knows type.
推荐答案
这是因为 get $中的类型转换c $ c>方法(应生成编译器警告)是未经检查的强制转换。调用
thing =(T)mObj;
时,编译器不知道 T
是什么,因此它无法确定
It's because the cast in the get
method (which should generate a compiler warning) is an unchecked cast. The compiler does not know what T
is when you call thing = (T) mObj;
so it cannot know if the cast should not compile.
编译后,由于类型擦除,生成的字节码将调用方法 get
返回 Object
(已删除 T
并替换为 Object
),并将类型转换简单地转换为:
After compilation, and due to type erasure, the bytecode generated invokes the method get
which returns an Object
(T
is erased and replaced with Object
) and the cast is simply translated to:
Object thing = null;
try {
thing = mObj;
在之后执行检查,结果从 get
方法,即 int i = Test。< Integer> get();
等效于:
The check is being done after the result is returned from the get
method, i.e. int i = Test.<Integer> get();
is equivalent to:
Object o = Test.get();
int i = ((Integer) o).intValue();
这篇关于对泛型参数类型的错误转换不会在Java中引发ClassCastException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!