我正在创建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)
答案 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!");
}
}