java - Java 中的参数化方法 : try-catch does not catch ClassCastException (on Android)

标签 java android

考虑创建一个新对象并将其转换为捕获异常的 try-catch block 中的字符串。一切似乎都很好。但是,如果我们在参数化函数的类似 try-catch block 中将 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

最佳答案

由于类型删除的实现方式,

final T ret = (T) obj;

实际翻译成

final Object ret = (Object) obj;

parametrizedCastTest 的实际实现返回一个对象,但在调用 的任何地方,转换都在那里完成:

final String test2 = Test.<String> parametrizedCastTest();

成为

final String test2 = (String) Test.parametrizedCastTest();

这就是为什么 CCE 发生在与您预期不同的地方。

作为一般规则,泛型方法是通过将类型变量替换为它们的上限(在本例中为 Object)来实现的,然后它们的调用站点 secret 地进行实际转换为您的类型我们应该出去。

关于java - Java 中的参数化方法 : try-catch does not catch ClassCastException (on Android),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27153731/

相关文章:

java - 在 Java 中停止线程时需要调用 join() 吗?

android - 上传时获取 JSON 异常

java - Retrofit 中未调用 onResponse 方法?

java - 如何列出Java类的所有实例方法?

java - Firebase admin java SDK - 当事件发生时获取更改数据而不是所有数据

java - 如何使用 JAXB 确保架构可扩展性

Android 应用程序在请求权限之前崩溃

java - 读取 install4j 中的属性文件

android - 从 url 下载和存储图像

Android:如何限制下载速度