try-finally块的奇怪异常行为

时间:2014-10-16 12:56:11

标签: java android exception-handling

我正在创建Android应用程序,当使用try-finally bock时,会发生一些与处理异常相关的奇怪行为。

为什么以下代码的输出为NullPointerException而不是SocketTimeoutException

consumeSomeService();
[...]
private void consumeSomeService() {
    try {
        getResponse();

    } catch (SocketTimeoutException ste) {
        Log.d("tag", "SocketTimeoutException");

    } catch (Exception e) {
        Log.d("tag", e.getClass().getName());
    }
}

private static void getResponse() throws SocketTimeoutException {
    try {
        throw new SocketTimeoutException();

    } finally {
        Log.d("tag", "finally!"); // No matter what is here, always throw NullPointerException
    }
}

如果删除finally块,它会按预期工作。

PC /桌面上的相同代码会正确地生成SocketTimeoutException

编辑:堆栈跟踪,其中“MyActivity.java:38”始终是finally块内的最后一行。

java.lang.NullPointerException
at mycompany.exceptiontest.MyActivity.getResponse(MyActivity.java:38)
at mycompany.exceptiontest.MyActivity.consumeSomeService(MyActivity.java:21)
at mycompany.exceptiontest.MyActivity.onCreate(MyActivity.java:16)
at android.app.Activity.performCreate(Activity.java:5104)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
at android.app.ActivityThread.access$600(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5041)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
at dalvik.system.NativeStart.main(Native Method)

1 个答案:

答案 0 :(得分:0)

将评论转换为答案以提供更多空间......

下面是一些基本的想法,它们测试了我们对正在发生的事情的所有假设。

我认为GenyMotion运行Android的真实副本,因此我希望它与设备运行相同。

在运行4.4.4的真实Nexus 7上进行测试,它按预期进行。


通过放置一些不可能抛出空指针异常的代码来测试finally

private static void getResponse() throws SocketTimeoutException {
    try {
        throw new SocketTimeoutException();
    } finally {
        int i = 1;
        if (i==1) {i++;}
    }
}

在这种情况下看哪一行会产生问题会很有趣。


通过投掷其他内容来测试SocketTimeoutException的问题。

private void consumeSomeService() {
    try {
        getResponse();
    } catch (Exception e) {
        Log.d("tag", e.getClass().getName());
    }
}

private static void getResponse() throws Exception {
    try {
        throw new Exception();
    } finally {
        Log.d("tag", "finally!");
    }
}

对于兴趣,通过内联方法getResponse()来测试行为。

private void consumeSomeService() {
    try {
        throw new SocketTimeoutException();
    } catch (SocketTimeoutException ste) {
        Log.d("tag", "SocketTimeoutException");
    } catch (Exception e) {
        Log.d("tag", e.getClass().getName());
    } finally {
        Log.d("tag", "finally!");
    }

}