異常:錯誤在我們編寫程序的過程中會經常發生,包括編譯期間和運行期間的錯誤(Throwable:有兩個重要的子類:Exception和Error)。
a、Error是程序無法處理的錯誤,表示運行應用程序中較嚴重問題。
b、Exception是程序本身可以處理的異常。異常處理通常指針對這種類型異常的處理。
c、非檢查異常(Unchecked Exception):編譯器不要求強制處。
d、檢查異常(Checked Exception):編譯器要求必須處置的異常。
Ps:同類就不舉例了,肯定可以的。
Ps1:若在 main 方法 throws 拋出的時候就是拋給虛擬機了。
Ps2:可以拋出與throw對象相同的類型或者其父類。
Ps3:如果要拋出(throw)異常,儘量不要拋一些非檢查型異常,沒有太大意義,因爲本來就編譯器不會檢查。
public class HotelAgeException extends Exception {
public HotelAgeException(){
super("18歲以下,80歲以上的住客必須由親友陪同");
}
}
public class TryDemoFour {
public static void main(String[] args) {
try {
testAge();
} catch (HotelAgeException e) {
System.out.println(e.getMessage());
System.out.println("酒店前臺工作人員不允許辦理入住登記");
}catch(Exception e){
e.printStackTrace();
}
}
/* throw拋出異常對象的處理方案:
* 1、通過try..catch包含throw語句--自己拋自己處理
* 2、通過throws在方法聲明出拋出異常類型--誰調用誰處理--調用者可以自己處理,也可以繼續上拋
* Ps:此時可以拋出與throw對象相同的類型或者其父類,不能是其子類。
* 3、若向上拋出和自己處理都存在的情況下,按照就近原則,優先選擇自己處理
*/
/*public static void testAge() { // 描述酒店的入住規則:限定年齡,18歲以下,80歲以上的住客必須由親友陪同
try {
System.out.println("請輸入年齡:");
Scanner input = new Scanner(System.in);
int age = input.nextInt();
if (age < 18 || age > 80) {
throw new Exception("18歲以下,80歲以上的住客必須由親友陪同");
} else {
System.out.println("歡迎入住本酒店");
}
} catch (Exception e) {
e.printStackTrace();
}
}*/
public static void testAge() throws HotelAgeException { // 此時可以拋出與throw對象相同的類型或者其父類,不能是其子類。
System.out.println("請輸入年齡:");
Scanner input = new Scanner(System.in);
int age = input.nextInt();
if (age < 18 || age > 80) {
//throw new ArithmeticException(); // 即使沒有throws也不會CE,因爲屬於非檢查型異常
//throw new Exception("18歲以下,80歲以上的住客必須由親友陪同"); // 若沒有throws會CE,因爲裏面包含檢查型異常
throw new HotelAgeException();
} else {
System.out.println("歡迎入住本酒店");
}
}
}
Ps:我們以爲的異常鏈(如上圖)~
public class TryDemoFive {
public static void main(String[] args) {
try {
testThree();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void testOne() throws HotelAgeException {
throw new HotelAgeException();
}
public static void testTwo() throws Exception {
try {
testOne();
} catch (HotelAgeException e) {
throw new Exception("我是新產生的異常1",e);
}
}
public static void testThree() throws Exception {
try {
testTwo();
} catch (Exception e) {
// 方案一
Exception e1=new Exception("我是新產生的異常2");
e1.initCause(e);
throw e1;
// 方案二
// throw new Exception("我是新產生的異常2",e);
}
}
}
Ps:操作方案
- 方案一:initCause(e)
- 方案二:通過在 new 異常(第一參數,e); 中的第二參數中,把 e 傳過去即可。
案例分析
- 異常父類必須放在子類的後面,否則CE,因爲按照順序下來,下面的子類異常就變成閒魚了。
- 一組try...catch...中,不能出現同類型的異常。
- 推薦在 catch 最後都補上 Exception 類型。
- 終止 finally 方法:箭頭所標識的地方都不會被執行到。System.exit(非零值即可)。
- System.exit(0)是將你的整個虛擬機裏的內容都停掉了 ,而dispose()只是關閉這個窗口,但是並沒有停止整個application exit() 。無論如何,內存都釋放了!也就是說連JVM都關閉了,內存里根本不可能還有什麼東西。
- System.exit(0)是正常退出程序,而System.exit(1)或者說非0表示非正常退出程序。
- System.exit(status)不管status爲何值都會退出程序。和return 相比有以下不同點:return是回到上一層,而System.exit(status)是回到最上層。
- 如果在finally中寫return,不管try or catch中是否有return,最後都以finally的return爲最終結果(不建議在finally中寫return,否則失去把上面的try or catch的return屏蔽掉了)。
- finally是在return後面的表達式運算後執行的(此時並沒有返回運算後的值,而是先把要返回的值保存起來,不管finally中的代碼怎麼樣,返回的值都不會改變,任然是之前保存的值),所以函數返回值是在finally執行前確定的。
- 常見異常錯誤