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();
}
沒有留言:
張貼留言