您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“Java關鍵字throw、throws、Throwable怎么用”,內容詳細,步驟清晰,細節處理妥當,希望這篇“Java關鍵字throw、throws、Throwable怎么用”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
throw,意為“投擲、拋、扔”。Throw、Throws和Throwable三者都用于異常處理。
Throwable在Java中是異常處理這個分支的頂級父類,其它所有異常處理的實現都依賴于Throwable
打開Java官方文檔(Java8版本),找到Throwable,它的直接子類為Error和Exception。
Error和Exception兩者的特點在于Error異常程序無法處理,只能交由人工介入修改代碼,比如棧溢出、堆溢出等等;而Exception異常可以提前發覺,并作出有效處理。
在Error中,常見的有棧溢出和堆溢出等等。
舉個例子,StackOverflowError
public class ErrorTest { public static void main(String[] args) { main(args); } }
無限遞歸,執行這個程序就會報棧溢出異常。
再比如堆異常,OutOfMemoryError
public class ErrorTest { public static void main(String[] args) { Integer[] testArray = new Integer[1024*1024*1024]; } }
在Exception中就有非常多我們所熟知的異常情況了,比如NullPointerException(空指針異常)、ArrayIndexOutOfBoundsException(數組下標越界)、NumberFormatException(數字格式化異常)等等。
public class ExceptionTest { public static void main(String[] args) { int[] testArray = null; System.out.println(testArray[0]); //空指針異常 } }
public class ExceptionTest { public static void main(String[] args) { int[] testArray = new int[3]; System.out.println(testArray[3]); //數組下標越界 } }
public class ExceptionTest { public static void main(String[] args) { String num = "abc"; System.out.println(Integer.parseInt(num)); //數字格式化異常 } }
throws應用在方法聲明處,指明此方法在執行時可能會出現的異常類型。一旦該方法執行時出現異常,就會在異常代碼處生成一個異常類的對象,此對象滿足Throws后的異常類型時,就會被拋出。這里有兩個過程,代碼有異常時
1. 生成一個異常對象;
2. throws捕獲到這個異常,將異常對象拋出
throws和try-catch-finally一起稱為異常處理的兩種方式。
try-catch-finally是在出現異常時主動處理掉異常,使得程序可以繼續執行下去;而throws捕獲到異常之后向上拋出異常對象,不去真正地處理這個異常。
所謂向上拋出異常對象,是將異常對象交給調用者去處理,比如方法A調用方法B,B通過throws拋出異常,而A可以選擇使用try-catch-finally處理掉異常,也可以通過throws繼續向上拋出異常對象,直到異常被真正處理掉。如果一直沒有方法去處理異常,異常對象最終會被拋給JVM,從而導致程序停止運行。
@Test public void throwsTest(){ //調用者解決拋出的異常 try{ formatChange("abc"); } catch (NumberFormatException e){ System.out.println("轉換格式錯誤!"); } catch (Exception e){ System.out.println("出現錯誤"); } } private int formatChange(String str) throws NumberFormatException{ //出現異常向上拋出 return Integer.parseInt(str); }
——如何選擇try-catch-finally還是throws?
當一個方法中存在異常需要處理,在大多數情況下,既可以選擇try-catch-finally直接處理掉這個異常,也可以選擇throws向上拋出異常,交給調用者去處理(異常拋到最后,總要有一方真正地去處理這個異常,怎么處理?還是用try-catch-finally唄),在選擇上比較自由,但是,出現以下兩種情況時,需要遵循一定的規則(如有補充,敬請指出)。
如果父類中被重寫的方法沒有使用throws拋出異常,則子類重寫的方法也不能使用throws拋出異常,也就意味著這種情況必須使用try-catch-finally去處理。
在方法A中,先后調用了另外的幾種方法,這幾種方法是遞進關系執行的且其中很多方法都存在異常需要處理,這種情況建議被調用的幾個方法使用throws向上拋出異常,在方法A中,使用try-catch-finally統一處理掉這些異常。
針對第一條,這是一個規定,子類中重寫的方法使用throws拋出的異常必須不大于父類中被重寫的方法拋出異常的范圍。舉個例子,父類中的方法B拋出NullPointerException異常,則子類中重寫B方法就不能拋出如Exception這種比NullPointerException范圍更大的異常;如果父類中被重寫的方法沒有拋出任何異常,則子類更不能拋出異常。
為什么?展示一段代碼。
//假設父類中的方法B拋出NullPointerException異常,子類中的方法B可以拋出Exception private void test(ParentClassTest parent){ try{ parent.B(); } catch(NullPointerException e){ System.out.println("出現了空指針異常"); } }
在本示例中,假設父類中的方法B拋出NullPointerException異常,子類中重寫的方法B可以拋出Exception。那么傳進給test方法的參數如果是父類的實例化對象,那么調用test方法沒有任何問題。如果傳進的參數是子類的實例化對象,再去調用子類重寫的方法B,那么就有可能拋出Exception異常,try-catch結構就壓不住這個異常了,這顯然是一個不合理的操作。
針對第二條,假設方法A中調用了方法C、D、E,這三個方法都有可能產生異常,且存在遞進關系,也就是D、E執行需要C執行完成、E執行依賴C、D執行完成。那么就推薦在C、D、E中向上拋出異常,在方法A中集中處理。為什么?如果C、D、E都是向上拋出異常,而A使用try-catch-finally去處理這個異常,如果某個方法真的出現異常,則不再繼續執行。而如果C、D、E都使用try-catch-finally直接解決掉異常,那么即使產生了異常,方法A也不會接收到異常的產生,那么還會接著往下執行,但是C出現了異常,再執行D、E沒有任何意義。
如果在程序編寫時有手動拋出異常的需求,則可以使用throw
throw使用在方法體內。與try-catch-finally和throws都不同,異常處理的兩個階段:1.遇到異常,生成異常對象;2.捕獲到異常,進行拋出或處理。try-catch-finally和throws都處在第二個階段,都是捕獲到異常后的相關處理,一般使用系統根據異常類型自動生成的異常對象進行處理。而throw應用在第一階段,手動地產生一個異常對象。
舉一個例子,判斷一個數值是否為非負數,如果為負數,則拋出異常。
class ThrowTest{ private int Number; public void judge(int num){ if(num>=0){ this.Number = num; } else{ throw new RuntimeException("傳入參數為負數"); } } }
@Test public void test2(){ ThrowTest throwTest = new ThrowTest(); throwTest.judge(-100); }
成功拋出異常。
使用try-catch捕獲一下異常。
@Test public void test2(){ ThrowTest throwTest = new ThrowTest(); try{ throwTest.judge(-100); } catch (RuntimeException e){ System.out.println(e.getMessage()); } }
如果把throw拋出的異常改為Exception,則直接報錯,也就是不能編譯。Exception包含兩種異常:編譯時異常和運行時異常,前者在編譯前就要檢查是否有可能產生編譯時異常;后者是在編譯后運行時才會判斷的異常。而throw new Exception包含了編譯時異常,需要顯式處理掉這個異常,怎么處理?try-catch-finally或者throws
class ThrowTest{ private int Number; public void judge(int num) throws Exception{ if(num>=0){ this.Number = num; } else{ throw new Exception("傳入參數為負數"); } } }
調用方也要隨著進行更改。
@Test public void test2(){ ThrowTest throwTest = new ThrowTest(); try{ throwTest.judge(-100); } catch (RuntimeException e){ System.out.println(e.getMessage()); } catch (Exception e){ System.out.println(e.getMessage()); } }
——自定義異常類
throw還可以拋出自定義異常類。
自定義異常類的聲明需要繼承于現有的異常體系。
class MyException extends RuntimeException{ static final long serialVersionUID = -703489719076939L; //可以認為是一種標識 public MyException(){} public MyException(String message){ super(message); } }
此時我們可以拋出自定義的異常
class ThrowTest{ private int Number; public void judge(int num) throws MyException{ if(num>=0){ this.Number = num; } else{ throw new MyException("不能輸入負數"); } } }
調用者修改
@Test public void test2(){ ThrowTest throwTest = new ThrowTest(); try{ throwTest.judge(-100); } catch (MyException e){ System.out.println(e.getMessage()); } }
讀到這里,這篇“Java關鍵字throw、throws、Throwable怎么用”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。