try{ ... } catch(物件型態 ex){ ... }簡單說,當try區塊裡的程式碼執行錯誤時,就執行例外處理catch裡的程式碼,catch會有一個參數,是Java把錯誤包裝成錯誤的物件型態。
例1:
class Try1Demo { public static void main(String[] args) { try { System.out.println(1 / 0); } catch (Exception ex) { System.out.println("something wrong"); } } }1/0是個致命錯誤,但我們用TryCatch去處理,當1/0錯誤時,就執行catch的程式碼,會顯示something wrong。 Exception錯誤物件的形態,因:
除以 0 的致命錯誤屬於 ArimethicException 類別,而 ArimethicException 繼承自 RuntimeException , RuntimeException 又繼承自 Exception ,事實上,所有例外均繼承自 Exception ,因此使用 Exception 可抓住所有例外。所以catch裡的參數可放不同的錯誤物件型態,這裡也可放ArithmeticException型態的物件,也可這樣寫,兩個catch:
class Try3Demo { public static void main(String[] args) { try { System.out.println(1 / 0); } catch (ArithmeticException ex) { System.out.println("算術錯誤的例外"); } catch (Exception ex) { System.out.println("something wrong"); } } }那我們怎麼知道錯誤的時候,他是什麼型態?
試著把例1的的TryCatch拿掉,執行後會顯示
Exception in thread "main" java.lang.ArithmeticException: / by zero這樣,通常可以知道是什麼型態的物件。
at trycatch.TryCatch.main(TryCatch.java:25)
C:\Users\...\AppData\Local\NetBeans\Cache\8.1\executor-snippets\run.xml:53: Java returned: 1
例2,一個計算平均的程式,輸入0就停止並運算:
package trycatch; import java.util.Scanner; public class TryCatch { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); double sum = 0; int count = 0; int number; while(true) { number = scanner.nextInt(); if(number == 0) { break; } sum += number; count++; } System.out.printf("平均 %.2f%n", sum / count); } } run結果: d5 Exception in thread "main" java.util.InputMismatchException at java.util.Scanner.throwFor(Scanner.java:864) at java.util.Scanner.next(Scanner.java:1485) at java.util.Scanner.nextInt(Scanner.java:2117) at java.util.Scanner.nextInt(Scanner.java:2076) at trycatch.TryCatch.main(TryCatch.java:10) C:\Users\...\AppData\Local\NetBeans\Cache\8.1\executor-snippets\run.xml:53: Java returned: 1 BUILD FAILED (total time: 10 seconds)輸入非數字,程式會錯誤。
這時可以根據系統吐出的錯誤訊息,來做例外處理,可以看到第22行,InputMismatchException就是錯誤的物件,因此可更改程式為:
package trycatch; import java.util.InputMismatchException; import java.util.Scanner; public class TryCatch { public static void main(String[] args) { try { Scanner scanner = new Scanner(System.in); double sum = 0; int count = 0; int number; while(true) { number = scanner.nextInt(); if(number == 0) { break; } sum += number; count++; } System.out.printf("平均 %.2f%n", sum / count); } catch(InputMismatchException ex){ System.out.println("必須輸入整數"); } } }這樣就可以應對輸入非數字的處理了。
例3,有時如果你這樣寫,竟然無緣無故錯誤:
public static void main(String[] args) { int ch = System.in.read(); System.out.println(ch); } run: Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - unreported exception java.io.IOException; must be caught or declared to be thrown at trycatch.TryCatch.main(TryCatch.java:5) C:\Users\...\AppData\Local\NetBeans\Cache\8.1\executor-snippets\run.xml:53: Java returned: 1有兩種方法解決,一、用try、catch包裹System.in.read(),二、在main()方法旁宣告throws java.io.IOException。
像下面這樣:
try { int ch = System.in.read(); System.out.println(ch); } catch(java.io.IOException ex) { ex.printStackTrace() ; }那為什麼這個例子一定要處理它呢?例1不處理一樣也可以跑啊。
這時就要了解錯誤物件的繼承架構:
Error:表示嚴重的系統錯誤,也可用try catch捕捉,但最好不要。
Exception:是程式設計本身的錯誤,最好用它或它的子類別實例來處理。
回到剛剛的System.in.read(),in是System的靜態成員,翻一下API文件,或如果你用NetBeans,按著Ctrl+滑鼠點一下變數名稱,可以發現in的形態就是java.io.InputStream,而它裡面有個read()方法,實際程式碼:
public abstract int read() throws IOException;而IOException是Exception的子類別,也就是說,除了RuntimeException和他以下的類別,IOException、ReflectiveOperationException、InterruptedException.....等等這些都是給編譯器檢查的,叫受檢例外(Checked Exception),通常受檢例外都要加上try catch。
而RuntimeException衍生出來的類別實例,叫執行時期例外,又稱非受檢例外(Unchecked Exception),編譯器不會檢查,是你自己要檢查的。
所以,例2,就是一種RuntimeException。
public static void main(String[] args) {
try {
System.in.read();
}
catch(Exception e) {
e.printStackTrace();
}
catch(java.io.IOException e) {
e.printStackTrace();
}
}
還有如果父類別物件比,子類別物件先被捕捉,那就會錯誤。try { System.in.read(); } catch(java.io.IOException e) { e.printStackTrace(); } catch(Exception e) { e.printStackTrace(); }必須改成這樣,子類別先做。
try { 作一些事... } catch(IOException | InterruptedException | ClassCastException e) { e.printStackTrace(); }這叫多重捕捉。
但多重捕捉不能有繼承關係:
try { 作一些事... } catch( Exception | IOException ) { e.printStackTrace(); }
沒有留言:
張貼留言