我在Java中遇到过泛型的行为,我完全无法理解(使用我的.NET背景).
public class TestGeneric<T>
{
public void get (Object arg)
{
T temp = (T) arg;
System.out.println(temp.toString());
return;
}
}
TestGeneric<Integer> tg = new TestGeneric<Integer>();
tg.get("Crack!!!");
Run Code Online (Sandbox Code Playgroud)
请告诉我为什么我没有得到ClassCastException,而且,在Idea中我看到temp String在赋值后具有值"Crack!!!".另外,我怎么能抛出ClassCastException?我在Windows 7 x64上使用JDK 1.7.0_07.
das*_*ght 14
您没有获得类转换异常的原因是Java泛型是通过类型擦除实现的.与需要对CLS进行重大更改的.NET泛型不同,Java泛型完全在编译时处理.在运行时,将T忽略强制转换.为了在运行时检查类型,您需要存储Class<T>并使用其方法来检查传入的参数的类型:
public class TestGeneric<T>
{
private Class<T> genClass;
public TestGeneric(Class<T> t) {genClass = t;}
public void get (Object arg)
{
if (!genClass.isInstance(arg)) {
throw new ClassCastException();
}
T temp = (T) arg;
System.out.println(temp.toString());
return;
}
}
TestGeneric<Integer> tg = new TestGeneric<Integer>(Integer.class);
tg.get("Bang!!!"); // Now that's a real Bang!!!
Run Code Online (Sandbox Code Playgroud)
小智 7
这是因为泛型类型T没有定义的边界,因此它被视为一个Object.ClassCastException在这种情况下,将某些东西投射到T不会导致.
但是,如果您的类定义是public class TestGeneric<T extends Number>,那么如果将String传入get(),则会得到ClassCastException.
考虑通用代码被"擦除"的非通用代码看起来是一种有益的练习:
public class TestGeneric
{
public void get (Object arg)
{
Object temp = (Object) arg;
System.out.println(temp.toString());
return;
}
}
TestGeneric tg = new TestGeneric();
tg.get("Crack!!!"); // should there be any problem?
Run Code Online (Sandbox Code Playgroud)
如果你这样做,你甚至不需要检查ClassCastException,它甚至无法编译。
public class TestGeneric<T> {
public void get (T arg){
System.out.println(arg.toString());
}
}
TestGeneric<Integer> tg = new TestGeneric<Integer>();
tg.get("Crack!!!");
Run Code Online (Sandbox Code Playgroud)