考虑创建一个新的Object并将其转换为捕获异常的try-catch块中的String。一切似乎都没问题。但是如果我们在参数化函数中的类似try-catch块中将Object转换为T会发生什么?没有捕获异常,程序崩溃引发ClassCastException。
更新:感谢您的回答和评论。但只是为了澄清:我理解为什么异常上升(因为显然将Object转换为String)。
问题是:为什么它在方法体中的运行时没有捕获ClassCastException?
class test
{
public void doTests()
{
Log.i("", "====== CLASS CAST TEST ======");
Log.i("", "====== REGULAR CAST TEST ");
final String test1 = test.regularCastTest(); // the exception thrown is catched within the method
Log.i("", "====== PARAMETRIZED CAST TEST ");
final String test2 = test.<String>parametrizedCastTest(); // fails here with ClassCastException without catching it
Log.i("", "------ CLASS CAST TEST END --");
}
static <T> T parametrizedCastTest()
{
Object obj = new Object();
try
{
final T ret = (T) obj;
Log.d("", String.format("%s; %s", obj.getClass().getSimpleName(), ret.getClass().getSimpleName())); // does not fail and prints 'Object; Object'
return ret;
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
static String regularCastTest()
{
Object obj = new Object();
try
{
final String ret = (String) obj;
return ret;
}
catch (Exception e)
{
e.printStackTrace();
}
return "";
}
}
PS:如果我们只是调用它而没有得到如下结果,那么参数化方法不会失败:
test.<String>parametrizedCastTest();
logcat的
11-26 19:13:37.692: I/(13018): ====== CLASS CAST TEST ======
11-26 19:13:37.692: I/(13018): ====== REGULAR CAST TEST
11-26 19:13:37.692: W/System.err(13018): java.lang.ClassCastException: java.lang.Object cannot be cast to java.lang.String
11-26 19:13:37.692: W/System.err(13018): at com.kaypu.goods.test.regularCastTest(test.java:57)
11-26 19:13:37.692: W/System.err(13018): at com.kaypu.goods.test.go1(test.java:30)
11-26 19:13:37.692: W/System.err(13018): at com.kaypu.goods.AppGoods.doTests(AppGoods.java:285)
11-26 19:13:37.692: W/System.err(13018): at com.kaypu.goods.AppGoods.onCreate(AppGoods.java:188)
11-26 19:13:37.692: W/System.err(13018): at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1007)
11-26 19:13:37.692: W/System.err(13018): at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4473)
11-26 19:13:37.692: W/System.err(13018): at android.app.ActivityThread.access$1500(ActivityThread.java:144)
11-26 19:13:37.692: W/System.err(13018): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1265)
11-26 19:13:37.692: W/System.err(13018): at android.os.Handler.dispatchMessage(Handler.java:102)
11-26 19:13:37.692: W/System.err(13018): at android.os.Looper.loop(Looper.java:136)
11-26 19:13:37.692: W/System.err(13018): at android.app.ActivityThread.main(ActivityThread.java:5146)
11-26 19:13:37.692: W/System.err(13018): at java.lang.reflect.Method.invokeNative(Native Method)
11-26 19:13:37.692: W/System.err(13018): at java.lang.reflect.Method.invoke(Method.java:515)
11-26 19:13:37.692: W/System.err(13018): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:732)
11-26 19:13:37.692: W/System.err(13018): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:566)
11-26 19:13:37.692: W/System.err(13018): at dalvik.system.NativeStart.main(Native Method)
11-26 19:13:37.692: I/(13018): ====== PARAMETRIZED CAST TEST
11-26 19:13:37.692: D/(13018): Object; Object
11-26 19:13:37.692: D/AndroidRuntime(13018): Shutting down VM
11-26 19:13:37.692: W/dalvikvm(13018): threadid=1: thread exiting with uncaught exception (group=0x415a2ce0)
11-26 19:13:37.692: E/AndroidRuntime(13018): FATAL EXCEPTION: main
11-26 19:13:37.692: E/AndroidRuntime(13018): Process: com.kaypu.goods, PID: 13018
11-26 19:13:37.692: E/AndroidRuntime(13018): java.lang.RuntimeException: Unable to create application com.kaypu.goods.AppGoods: java.lang.ClassCastException: java.lang.Object cannot be cast to java.lang.String
11-26 19:13:37.692: E/AndroidRuntime(13018): at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4476)
11-26 19:13:37.692: E/AndroidRuntime(13018): at android.app.ActivityThread.access$1500(ActivityThread.java:144)
11-26 19:13:37.692: E/AndroidRuntime(13018): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1265)
11-26 19:13:37.692: E/AndroidRuntime(13018): at android.os.Handler.dispatchMessage(Handler.java:102)
11-26 19:13:37.692: E/AndroidRuntime(13018): at android.os.Looper.loop(Looper.java:136)
11-26 19:13:37.692: E/AndroidRuntime(13018): at android.app.ActivityThread.main(ActivityThread.java:5146)
11-26 19:13:37.692: E/AndroidRuntime(13018): at java.lang.reflect.Method.invokeNative(Native Method)
11-26 19:13:37.692: E/AndroidRuntime(13018): at java.lang.reflect.Method.invoke(Method.java:515)
11-26 19:13:37.692: E/AndroidRuntime(13018): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:732)
11-26 19:13:37.692: E/AndroidRuntime(13018): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:566)
11-26 19:13:37.692: E/AndroidRuntime(13018): at dalvik.system.NativeStart.main(Native Method)
11-26 19:13:37.692: E/AndroidRuntime(13018): Caused by: java.lang.ClassCastException: java.lang.Object cannot be cast to java.lang.String
11-26 19:13:37.692: E/AndroidRuntime(13018): at com.kaypu.goods.test.go1(test.java:32)
11-26 19:13:37.692: E/AndroidRuntime(13018): at com.kaypu.goods.AppGoods.doTests(AppGoods.java:285)
11-26 19:13:37.692: E/AndroidRuntime(13018): at com.kaypu.goods.AppGoods.onCreate(AppGoods.java:188)
11-26 19:13:37.692: E/AndroidRuntime(13018): at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1007)
11-26 19:13:37.692: E/AndroidRuntime(13018): at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4473)
11-26 19:13:37.692: E/AndroidRuntime(13018): ... 10 more
答案 0 :(得分:3)
由于实现了类型擦除的方式,
final T ret = (T) obj;
实际上已翻译为
final Object ret = (Object) obj;
并且parametrizedCastTest
的实际实现会返回Object
,但无论在哪里调用,都会在那里完成转换:
final String test2 = Test.<String> parametrizedCastTest();
变为
final String test2 = (String) Test.parametrizedCastTest();
这就是为什么CCE发生在与你预期不同的地方。
作为一般规则,泛型方法是通过用它们的上限(在本例中为Object)替换类型变量来实现的,然后它们的调用站点秘密地将实际的转换为你的类型应该离开。
答案 1 :(得分:1)
你应该在这里发出警告
final T ret = (T) obj;
关于一个不安全的演员。
在泛型方法中,您对声明的类型参数的所有了解都是它的边界。您已将类型参数声明为
static <T> T parametrizedCastTest() {
没有界限。换句话说,它减少到Object
。演员在这里
final T ret = (T) obj;
是不安全的,因为用作返回类型的T
实际上可以是其他任何东西。在你的例子中它是。
final String test2 = Test.<String> parametrizedCastTest(); // fails here with ClassCastException without catching it
您尝试将Object
类型的对象分配给String
类型的变量。这将永远不会奏效。