2007年11月9日 星期五

Head First Java 讀後整理(8) - Risky Behavior

1、當 method 有可能會拋出例外時,就必須在設計時期進行處理 (如下圖)

import javax.sound.midi.*;
public class MusicTest1 {
public void play() {
try { //這裡若不進行例外處理,compiler 會產生錯誤訊息
//compiler 要確定你了解呼叫的 method 是有風險的
Sequencer sequencer = MidiSystem.getSequencer();
System.out.println("Successfully got a sequencer");
} catch(MidiUnavailableException e) {
System.out.println("Bummer");
} // close try
} // close play

public static void main(String[] args) {
MusicTest1 mt = new MusicTest1();
mt.play();
} // close main
} // close MusicTest1

2、例外是一種 Exception 型態的 object,所以程式中 cache 到的也是 object
所有例外皆是 extend Exception class 而來,而到底有哪些 class extend Exception 呢? 可以參考官方網站的文件

3、會拋出例外的 method 必須宣告它有可能會這麼做
//宣告可能會拋出的例外 => BadException
public void takeRisk() throws BadException {
if(abandonAllHope) //遇到拋出例外的情況
throw new BadException();
}

4、method 可以抓住其他 method 所拋出的例外,而例外總是丟回給呼叫方
public void crossFingers() {
try {
//此 method 可能會拋出 BadException 例外
anObject.takeRisk();
} catch(BadException e) { //必須處理可能會被拋出的 BadException
System.out.println("Got a BadException!");
e.printStackTrace(); //可透過 printStackTrace() 來取得有用的資訊
}
}

5、除了 RuntimeException 外,compiler 保證都可以檢查到
RuntimeException 被稱為 unchecked exception,開發程式時可以自己拋出並進行處理,但是這是非必要的,而 compiler 也不會去理會這個部分;因為 RuntimeException 的發生原因大多是程式邏輯上的錯誤,因此這是程式設計師必須排除的,compiler 自然也就不會去插手

6、method 是可以拋出多個例外的
public class Laundry {
//可宣告 method 拋出多個例外
public void doLaundry() throws PantsException, LingerieException { }
}

7、若 method 拋出多個 checked 例外,程式中就必須要全部處理(也可以只處理共同的 superclass Exception)
public class Foo {
public void go() {
Laundry laundry = new Laundry();

// =============== 第一種作法 ===============
try {
//此 method 會拋出兩個 checked Exception 需要事先處理
laundry.doLaundry();
} catch(PantsException e) {
//這邊處理 PantsException 例外
} catch(LingerieException e) {
//這邊處理 LingerieException 例外
}

// =============== 第二種作法 ===============
try {
//此 method 會拋出兩個 checked Exception 需要事先處理
laundry.doLaundry();
} catch(Exception e) {
//由於所有例外都是 extend Exception class 而來
//因此若沒有個別處理例外的需求,就只要處理 superclass 的 Exception 就可以了
}
} //close go
} //close Foo

8、Exception 是所有例外的 superclass

9、例外也是 polymorphism 的,因此可以:
  • 以例外的 supertype 來宣告會拋出的例外
  • 以所拋出例外的 supertype 來 catch 例外

10、可以用 super 來處理所有例外,並不代表就應該這麼做
如此作法會容易搞不清楚實際出錯的地方,因此還是建議針對例外作個別處理,除非真的每個例外都是使用相同的處理方式

11、有多個 catch 區塊時,要從小排到大(最底層的 subclass 到最上層的 superclass),否則 compiler 會顯示錯誤

12、如果不想處理例外,可以把它 duck 掉來避開 (但 ducking 只是在互踢皮球,但可以通過 compiler 的檢查)
public class Foo {
//這就是用 duck 迴避掉該進行的例外處理
public void go() throws PantsException, LingerieException {
Laundry laundry = new Laundry();
laundry.doLaundry(); //此 method 會拋出兩個 checked Exception 需要事先處理
} //close go
} //close Foo

沒有留言:

張貼留言