2 回答

TA貢獻2037條經驗 獲得超6個贊
為什么我們只能在 Throwable/Exception 對象上調用 Throwable.initCause() 一次?為什么如果原因異常是由構造函數(shù)設置的,那么我們不能使用 initCause() 再次設置它嗎?
Throwable.initCause() 允許我們使用不設置原因異常的構造函數(shù)實例化異常,并在第二次設置異常原因:
MyException e = new MyException();
e.initCause(rootException);
或者 :
MyException e = new MyException("error message...");
e.initCause(rootException);
因此,您必須將其視為接受原因異常作為參數(shù)的 arg 構造函數(shù)的替代方案:
MyException e = new MyException(rootException);
您可以一次設置原因異常,因為它不是為修改而設計的:如果為某個原因拋出異常,則該原因不會改變。
因此,為客戶端類提供這種可能性可能容易出錯。
但是語言設計者也允許設置原因異常,即使我們要實例化的異常類沒有提供接受原因異常作為參數(shù)的構造函數(shù)。于是他們介紹initCause()。
但在大多數(shù)情況下,您不想使用這種方法。調用傳遞異常原因的 arg 構造函數(shù)更簡單、更直接。
我們可以為異常設置多個原因嗎?
不,這是不可能的:由于單個直接異常可能會發(fā)生 n 異常。
但是異??赡苁怯啥鄠€中介/先前拋出的異常引起的。
因此,您可以將異常鏈接到 2 之外,如前面的示例所示:
MyException e = new MyException(rootException);
例如假設a()調用b(),c()如果發(fā)生錯誤,每個方法可能會拋出異常:
void a(){
try{
b();
}
catch(SecondException e){
throw new ThirdException(e);
}
}
void b(){
try{
c();
}
catch(FirstException e){
throw new SecondException(e);
}
}
void c(){
throw new FirstException();
}
如果所有這些方法都拋出自己的異常,你在最后的堆棧跟蹤3種鏈式異常ThirdException: ThirdException引起SecondException引起FirstException。
就像你寫過:
new ThirdException(new SecondException(new FirstException()));
但作為獎勵,每個創(chuàng)建的異常的線程執(zhí)行堆棧的快照。

TA貢獻1847條經驗 獲得超7個贊
這純粹是一種設計選擇。我不知道 Sun/Oracle 的原作者,但異常的整體設計似乎是它們應該被視為不可變對象。如果您考慮一下,這實際上是有道理的 - 如果異常在創(chuàng)建后可以更改,那肯定會使任何調試成為一場噩夢!
添加回答
舉報