異常
異常:就是程序出現的不正常的情況。
舉例:
錯誤:這是非常嚴重的問題,一般我們處理不了,一般在這裏指的是硬件問題。
異常:
編譯時期異常:開始就必須要處理的,如果不處理,後面就走不了。
運行時期異常:開始可以不用處理。這種問題一旦發生,就是我們的程序問題,需要我們修改程序。
體系結構:
Throwable:
Error:
Exception:
非RuntimeException:編譯時期異常
RuntimeException:運行時期異常
例如:比如除數不能爲0:java.lang.ArithmeticException: / by zero
public class ExceptionDemo2 {
public static void main(String[] args) {
System.out.println("start");
int a = 10;
int b = 0;
System.out.println(a/b);//java.lang.ArithmeticException: / by zero
System.out.println("end");
}
}
針對異常,JVM默認的處理方案:
- 一旦遇到程序出現了問題,就會把問題的類名,錯誤原因,錯誤的位置等信息打印在控制檯,以便我們觀察。並且,會自動從當前出問題的地方停止掉。
- 這種處理方案雖然可以,但是不夠好。 哪裏不好呢?
*其實程序出問題,不應該直接停止,因爲我們的程序可能是由多部分組成的,其中一個部分出問題了,不應該影響其他部分的執行。 - 所以,我們應該讓其他的部分能夠執行下去。
對於上面的問題我們有以下方案兩種方案:
try…catch…finally
throws
try…catch…finally:
try{
可能出現異常的代碼
}catch(異常類名 變量名) {
針對異常的代碼處理
}finally {
釋放資源的地方
}
簡化一下第一個:
try{
可能出現異常的代碼
}catch(異常類名 變量名) {
針對異常的代碼處理
}
public class ExceptionDemo3 {
public static void main(String[] args) {
System.out.println("start");
int a= 10;
int b = 0;
try{
//可能出現異常的代碼
System.out.println(a/b);//當除數爲0的時候會拋出ArithmeticException這個異常
//接着程序會拿着這個異常和catch裏面的異常類已經對比
}catch(ArithmeticException e){
//當程序拋出ArithmeticException這個異常之後給出的具體的處理方法
System.out.println("你的除數不能爲0");
}
System.out.println("end");
}
}
多個異常的處理:
1.針對每一個出現問題的地方寫一個try…catch語句
2.針對多個異常,採用一個try,多個catch的情況。
try…catch…catch…
注意:有多個catch時候,運行時,只能運行出一個錯誤,而程序不會返回到try
例如下面的程序運行結果:不能運行出除數爲0的結果,遇到try裏面的問題,就自動和catch裏面進行匹配。一旦匹配就執行catch裏面的內容,執行完畢後,接着執行後面的代碼。
注意:如果異常間有子父關係,父必須在最後。(因爲如果異常放在前面,則發生異常的時候都會被父類異常接受,後面會報錯)
package com.edu_01;
public class ExceptionDemo4 {
public static void main(String[] args) {
//多個異常處理的第一種解決方案
//A:給每一個可能出現異常的代碼全部加上try..catch..
/* try{
System.out.println(10/0);
}catch(ArithmeticException e){
System.out.println("除數不能爲0");
}
int[] arr = {1,2,3};
try{
System.out.println(arr[3]);//拋出IndexOutOfBoundsException這個異常
}catch(IndexOutOfBoundsException e){
System.out.println("數組越界了");
}*/
//B:針對多個異常,採用一個try,多個catch的情況。
//當存在多個catch情況下,如果異常類之間存在子父關係,那麼父類應該放到最後
int[] arr = {1,2,3};
try{
System.out.println(arr[3]);//拋出IndexOutOfBoundsException
System.out.println(10/0);//拋出ArithmeticException
arr = null;
System.out.println(arr[2]);//拋出空指針異常NullpointerException
}catch(IndexOutOfBoundsException e){//Exception e = new IndexOutOfBoundsException();
System.out.println("數組越界了");
}catch(ArithmeticException e){
System.out.println("除數不能爲0");
}catch(Exception e){//當前面的異常類都沒有匹配到之後,會自動匹配這個異常
System.out.println("出現了其他異常");
}
}
}
編譯時期異常和運行時期異常的區別:
- 編譯時期異常:Java程序必須顯示處理,否則程序就會發生錯誤,無法通過編譯
- FileNotFoundException(文件未找到異常)
- 運行時期異常:無需顯示處理,也可以和編譯時異常一樣處理
- ArithmeticException
Throwable中的方法:
- printStackTrace():打印異常信息,程序從出問題的地方開始就會打印創建一個該異常對應的對象,該對象直接調用打印方法。
public class ExceptionDemo6 {
public static void main(String[] args) {
try{
System.out.println(10/0);//當程序出問題了之後會拋出一個ArithmeticException的對象
//new ArithmeticException()
}catch(ArithmeticException e){//ArithmeticException e = new ArithmeticException();
e.printStackTrace();//打印異常信息
//java.lang.ArithmeticException: / by zero
//at com.edu_01.ExceptionDemo6.main(ExceptionDemo6.java:12)
}
}
}
throws
表示拋出異常,由該方法的調用者來處理,用在方法聲明後面,跟的是異常類名,可以跟多個異常類名,用“,”號隔開。
throws表示出現異常的一種可能,並不一定會發生這些異常。
try…catch 是直接進行了處理。而throws則是把異常處理的事情交給了調用者。throws用在方法上,聲明方法有異常,交給調用者處理。但是呢,如果是編譯時期異常,調用就必須處理。如果是運行時期異常,調用者可以處理,也可以不處理。
異常處理:
try…catch…finally
finally:一般用於釋放資源。在數據庫操作或者IO流比較常見。
特點:
被finally控制的語句體一定會執行
特殊情況:在執行到finally之前jvm退出了(比如System.exit(0))
public class ExceptionDemo8 {
public static void main(String[] args) {
try{
System.out.println(10/0);
}catch(ArithmeticException e){
System.out.println("除數爲0了");
//在執行finally語句體之前jvm虛擬機退出了,那麼就不會被執行
System.exit(0);
}finally{
//這個代碼塊裏面的代碼一定會被執行的
System.out.println("我是finally我一定會被執行");
}
}
}
final,finally的區別:
final:最終的意思。可以修飾類,方法,變量。
修飾類,類不能被繼承
修飾方法,方法不能被重寫
修飾變量,變量是常量
finally:
異常處理的一部分。被finally控制的代碼一定會執行。
特殊情況:在執行到finally之前,jvm退出了。
注意:
A:子類重寫父類方法時,子類的方法必須拋出相同的異常或父類異常的子類。(父親壞了,兒子不能比父親更壞)
B:如果父類拋出了多個異常,子類重寫父類時,只能拋出相同的異常或者是他的子集,子類不能拋出父類沒有的異常
C:如果被重寫的方法沒有異常拋出,那麼子類的方法絕對不可以拋出異常,如果子類方法內有異常發生,那麼子類只能try,不能throws
上述僅僅針對編譯時期異常,與運行時期異常無關。
throw和throws的區別:
throws:
用在方法聲明後面,跟的是異常類名
可以跟多個異常類名,用逗號隔開
表示拋出異常,由該方法的調用者來處理
throws表示出現異常的一種可能性,並不一定會發生這些異常
throw:
用在方法體內,跟的是異常對象名
只能拋出一個異常對象名
表示拋出異常,由方法體內的語句處理
throw則是拋出了異常,執行throw則一定拋出了某種異常!
注意:如果throw的是編譯時期異常,在方法聲明上必須用throws進行標記,如果throw的是運行時期異常,在方法聲明上可以用throws進行標記,也可以不用。
public class ThrowDemo {
public static void main(String[] args) {
method();
try {
method2();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
private static void method2() throws FileNotFoundException{
try{
FileInputStream fis = new FileInputStream("D://a.txt");
}catch(FileNotFoundException e){
//當遇見這個異常之後,直接拋出(這就是我給出的處理方法)
//如果【拋出的是編譯時期異常的話,必須在方法聲明上給予聲明
throw new FileNotFoundException();
}
}
private static void method() throws ArithmeticException{
int a = 10;
int b = 2;
if (b==0) {
//在這裏拋出的是運行時期異常,拋出這個異常的同時,可以在方法聲明上給予聲明,也可以不聲明
throw new ArithmeticException();
}else {
System.out.println(a/b);
}
}
}