前言
越是簡單,越容易忽略。編碼一切應該從簡單開始,簡單點,編碼的方式簡單點,正確點,對待異常的方式正確點。
一, JAVA異常類結構
Java異常類結構: Java異常類結構如下圖。基類爲Throwable,Error和Exception繼承Throwable,RuntimeException和IOException等繼承Exception,NullPointerException繼承RuntimeException,可以說,在Java中,除了Error之外,所有的異常類都直接或間接地繼承自Exception。
Java異常分類:
① ,非運行時/編譯時異常。在Java中,凡是繼承自Exception但不是繼承自RuntimeException的類都是非運行時異常,又稱爲編譯時異常。
② ,運行時異常。Error和所有直接或間接地繼承自RuntimeException的異常都是運行時異常,常見的有NullPointerException,IllegalArgumentException,IndexOutOfBoundsException等
Exception | 含義 |
---|---|
NullPointerException | 指針 |
IllegalArgumentException | 非法參數 |
IllegalStateException | 非法狀態 |
IndexOutOfBoundsException | 索引出界 |
UnsupportedOperationException | 不支持的操作 |
SQLException | 操作數據庫異常 |
ClassCastException | 數據類型轉換異常 |
NumberFormatException | 字符串轉換數字異常 |
ArithmeticException | 除數爲0的異常 |
BufferOverflowException | 緩衝區上溢異常 |
BufferUnderflowException | 緩衝區下溢異常 |
EmptyStackException | 空棧異常 |
二, Android異常分類
1, Java異常
在Java中出現未捕獲異常,導致程序異常終止退出。即上面說到的Java Exception中的RuntimeException。
2, ANR(Application Not Responding)
應用與用戶進行交互時,在一定時間(如主線程輸入事件中爲5秒)內沒有響應用戶的操作,則會引發ANR錯誤,並彈出一個系統提示框,讓用戶選擇繼續等待或立即關閉程序。同時會在/data/anr目錄下生成一個traces.txt文件,記錄系統產生ANR異常的堆棧和線程信息。
3, Native異常
Native異常/崩潰指在Native代碼(C/C++)中,因訪問非法地址,地址對齊等問題,或程序主動abort所產生相應的Signal導致程序異常退出。Linux中定義了很多Signal,當然並不是所有的Signal都會引發崩潰,一般會引發異常退出的Signal有SIGSEGV,SIGABRT,SIGILL,SIGBUS,SIGFPE等。Native異常具有與Java異常不同的特點:
- 程序會直接閃退到系統桌面。
- 出錯時不會彈出提示框提醒程序崩潰(Android5.0以下) 。
三, Android異常處理方法
1, 編譯時異常
在編譯階段被處理的異常,編譯器會強制程序處理所有的編譯時異常,也就是用try…catch顯式地捕獲並處理。Java認爲這類異常都是可以被處理/修復的,同時在Java API文檔的方法說明中,都會添加是否throw某個exception,這個exception就是編譯時異常。
2, 運行時異常
在運行時沒有相應的try…catch處理該異常對象,所以Java運行環境將會終止,程序將推出。針對這類異常處理方法:
- 認爲加try…catch。這是一種非常low,非常不可取的方法,因爲如果所有代碼都加try…catch,那麼對代碼真正問題所在,無法處理和解決該問題。當然這樣做並不是不可取。
- 個性化退出。我們可以在程序退出前,彈出一個個性化的對話框或者重啓應用來代替Android系統默認強制退出應用程序。實現方式可以查閱資料,這裏不做過多介紹。另外對於一些異常我們是可以做攔截操作的,比如空指針這類問題,如果出現了不讓程序崩潰,但是這些方式本人建議儘量不要去做。因爲程序中的異常本身可以看成是幫助我們查找問題,和提升程序的穩定性的,去掉或者中和掉得不償失。
四, 正確使用try…catch
- 需要異常捕獲的地方,比如:類型轉換等。不要隨意去添加異常,分析代碼穩定性。
- 如果有多個Exception,不要利用Exception捕獲所有潛在的異常。
- 如果try語句塊中存在return語句,那麼首先會執行finally語句塊中的代碼,然後才返回。
- 如果try語句塊中存在System.exit(0)語句,那麼不會執行finally語句塊的代碼,因爲System.exit(0)會終止當前運行的JVM,程序JVM終止前結束執行。
- 當使用多個catch語句塊來捕獲異常時,需要將父類的catch語句塊放到子類型的catch塊之後,這樣才能保證後續的catch可能被執行,否則子類型的catch將永遠無法到達,Java編譯器會報編譯錯誤。
- 不要將異常包含在for循環語句中,因爲異常處理是佔用資源的。