2014-10-16 55 views
0

我創建Android應用程序和一些奇怪的行爲正在發生與使用try-finally bock時處理異常有關。奇怪的異常行爲與try-finally塊

爲什麼下面代碼的輸出是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正確。

編輯:stacktrace,其中「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

@RichardLeMesurier:我使用的是Android Studio 0.8.9,我已經嘗試過兩種不同的GenyMotion模擬器(API 16和17)。沒有更多的代碼,只是onCreate()。如果從'finally'拋出另一個異常,則調用正確的catch。 – 2014-10-16 14:07:24

+0

使用Android 4.4.2與真正的三星Galaxy Tab 4(SM-T531)進行了測試,結果與錯誤行爲相同。 – 2014-10-30 10:50:14

回答

0

轉換評論回答提供更大的空間......

低於該測試我們對正在發生的事情的所有假設的一些基本思路。

我認爲GenyMotion運行Android的一個真正的副本,所以我希望它運行相同的設備。

在真正的Nexus 7上運行4.4.4,測試結果如預期。


通過放置一些不可能拋出空指針異常的代碼來測試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!"); 
    } 

} 
+0

「......放一些不可能拋出空指針異常的代碼」:NPE繼續在'finally'的最後一行後拋出...... – 2014-10-16 16:09:44

+0

「......拋出別的東西」:沒有區別。相同的NPE行爲。 – 2014-10-16 16:12:22

+0

「...通過內聯方法測試行爲」:它按預期工作,但由於實際應用程序涉及自動生成的代碼,因此無法使用此方法。 – 2014-10-16 16:16:54