淺析Java語言中兩種異常的差別

來源:互聯網
上載者:User

  Java提供了兩類主要的異常:runtime exception和checked exception。所有的checked exception是從java.lang.Exception類衍生出來的,而runtime exception則是從java.lang.RuntimeException或java.lang.Error類衍生出來的。

  它們的不同之處表現在兩方面:機制上和邏輯上。

  一、機制上

  它們在機制上的不同表現在兩點:1.如何定義方法;2. 如何處理拋出的異常。請看下面CheckedException的定義:

  public class CheckedException extends Exception 
  { 

  public CheckedException() {} 
  public CheckedException( String message ) 
  { 
  super( message ); 
  } 
  } 
  以及一個使用exception的例子:

  public class ExceptionalClass 
  { 

  public void method1() 
  throws CheckedException 
  { 
   // ... throw new CheckedException( “...出錯了“ ); 
  } 
  public void method2( String arg ) 
  { 
   if( arg == null ) 
   { 
    throw new NullPointerException( “method2的參數arg是null!” ); 
   } 
  } 
  public void method3() throws CheckedException 
  { 
   method1(); 
  } 
  } 

  你可能已經注意到了,兩個方法method1()和method2()都會拋出exception,可是只有method1()做了聲明。另外,method3()本身並不會拋出exception,可是它卻聲明會拋出CheckedException。在向你解釋之前,讓我們先來看看這個類的main()方法:

  public static void main( String[] args ) 
  { 

  ExceptionalClass example = new ExceptionalClass(); 
  try 
  { 
  example.method1(); 
  example.method3(); 
  } 
  catch( CheckedException ex ) { } example.method2( null ); 
  } 

  在main()方法中,如果要調用method1(),你必須把這個調用放在try/catch程式塊當中,因為它會拋出Checked exception。

  相比之下,當你調用method2()時,則不需要把它放在try/catch程式塊當中,因為它會拋出的exception不是checked exception,而是runtime exception。會拋出runtime exception的方法在定義時不必聲明它會拋出exception。

  現在,讓我們再來看看method3()。它調用了method1()卻沒有把這個調用放在try/catch程式塊當中。它是通過聲明它會拋出method1()會拋出的exception來避免這樣做的。它沒有捕獲這個exception,而是把它傳遞下去。實際上main()方法也可以這樣做,通過聲明它會拋出Checked exception來避免使用try/catch程式塊(當然我們反對這種做法)。

  小結一下:

  * Runtime exceptions:

  在定義方法時不需要聲明會拋出runtime exception;

  在調用這個方法時不需要捕獲這個runtime exception;

  runtime exception是從java.lang.RuntimeException或java.lang.Error類衍生出來的。

  * Checked exceptions:

  定義方法時必須聲明所有可能會拋出的checked exception;

  在調用這個方法時,必須捕獲它的checked exception,不然就得把它的exception傳遞下去;

  checked exception是從java.lang.Exception類衍生出來的。

  二、邏輯上

  從邏輯的角度來說,checked exceptions和runtime exception是有不同的使用目的的。checked exception用來指示一種調用方能夠直接處理的異常情況。而runtime exception則用來指示一種調用方本身無法處理或恢複的程式錯誤。

  checked exception迫使你捕獲它並處理這種異常情況。以java.net.URL類的構建器(constructor)為例,它的每一個構建器都會拋出MalformedURLException。MalformedURLException就是一種checked exception。設想一下,你有一個簡單的程式,用來提示使用者輸入一個URL,然後通過這個URL去下載一個網頁。如果使用者輸入的URL有錯誤,構建器就會拋出一個exception。既然這個exception是checked exception,你的程式就可以捕獲它並正確處理:比如說提示使用者重新輸入。

  再看下面這個例子:

  public void method() 
  { 

  int [] numbers = { 1, 2, 3 }; 
  int sum = numbers[0] numbers[3]; 
  } 

  在運行方法method()時會遇到ArrayIndexOutOfBoundsException(因為數組numbers的成員是從0到2)。對於這個異常,調用方無法處理/糾正。這個方法method()和上面的method2()一樣,都是runtime exception的情形。上面我已經提到,runtime exception用來指示一種調用方本身無法處理/恢複的程式錯誤。而程式錯誤通常是無法在運行過程中處理的,必須改正程式碼。

  總而言之,在程式的運行過程中一個checked exception被拋出的時候,只有能夠適當處理這個異常的調用方才應該用try/catch來捕獲它。而對於runtime exception,則不應當在程式中捕獲它。如果你要捕獲它的話,你就會冒這樣一個風險:程式碼的錯誤(bug)被掩蓋在運行當中無法被察覺。因為在程式測試過程中,系統列印出來的呼叫堆疊路徑(StackTrace)往往使你更快找到並修改代碼中的錯誤。有些程式員建議捕獲runtime exception並紀錄在log中,我反對這樣做。這樣做的壞處是你必須通過瀏覽log來找出問題,而用來測試程式的測試系統(比如Unit Test)卻無法直接捕獲問題並報告出來。

  在程式中捕獲runtime exception還會帶來更多的問題:要捕獲哪些runtime exception?什麼時候捕獲?runtime exception是不需要聲明的,你怎樣知道有沒有runtime exception要捕獲?你想看到在程式中每一次調用方法時,都使用try/catch程式塊嗎?

相關文章

Beyond APAC's No.1 Cloud

19.6% IaaS Market Share in Asia Pacific - Gartner IT Service report, 2018

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。