接口和異常

接口

接口,是Java語言中一種引用類型,是方法的集合。接口的內部主要就是封裝了方法,包含抽象方法(JDK 7及之前),默認方法和靜態方法(JDK 8),私有方法 (JDK 9)。前端

接口的定義

接口定義:java

它與定義類方式類似,可是使用 interface 關鍵字。它也會被編譯成.class文件,但必定要明確它並非類,而是另一種引用數據類型。程序員

引用類型:數組、類、接口數據庫

接口語法:編程

1  public interface 接口名稱 {
2      // 常量
3      // 抽象方法
4      // 默認方法 
5      // 靜態方法
6      // 私有方法 
7  }

常量

接口當中也能夠定義「成員變量」,可是必須使用public static final三個關鍵字進行修飾。從效果上看,這其實就是接口的【常量】數組

語法編程語言

1 public static final 數據類型 常量名稱 = 數據值;

備註:一旦使用final關鍵字進行修飾,說明不可改變ide

注意事項:ui

1. 接口當中的常量,能夠省略public static final,注意:不寫也照樣是這樣。spa

2. 接口當中的常量,必須進行賦值;不能不賦值。

3. 接口中常量的名稱,使用徹底大寫的字母,用下劃線進行分隔。(推薦命名規則)

抽象方法

抽象方法:使用 abstract 關鍵字修飾,能夠省略,沒有方法體。該方法供子類實現使用。

語法:

1 public interface InterFaceName {     
2     public abstract void method(); 
3 }

默認方法

默認方法:使用 default 修飾,不可省略,供子類調用或者子類重寫。

語法:

1 public interface InterFaceName {     
2     public default void method() {         
3         // 執行語句     
4     }
5 }

備註:接口當中的默認方法,能夠解決接口升級的問題。及能夠後期進行重寫升級。

靜態方法

靜態方法:使用 static 修飾,供接口直接調用。

1  public interface InterFaceName {     
2     public static void method2() {         
3         // 執行語句         
4     }
5  }

私有方法

普通私有方法

普通私有方法:解決多個默認方法之間重複代碼問題。

格式

1 private 返回值類型 方法名稱(參數列表) {
2     方法體
3 }
 1 public interface MyInterfacePrivateA {
 2 
 3     public default void methodDefault1() {
 4         System.out.println("默認方法1");
 5         methodCommon();
 6     }
 7 
 8     public default void methodDefault2() {
 9         System.out.println("默認方法2");
10         methodCommon();
11     }
12 
13     // 普通私有方法
14     private void methodCommon() {
15         System.out.println("AAA");
16         System.out.println("BBB");
17         System.out.println("CCC");
18     }
19 
20 }
代碼示例:解決默認方法代碼重複問題

靜態私有方法

靜態私有方法:解決多個靜態方法之間重複代碼問題

格式

1 private static 返回值類型 方法名稱(參數列表) {
2     方法體
3 }
 1 public interface MyInterfacePrivateB {
 2 
 3     public static void methodStatic1() {
 4         System.out.println("靜態方法1");
 5         methodStaticCommon();
 6     }
 7 
 8     public static void methodStatic2() {
 9         System.out.println("靜態方法2");
10         methodStaticCommon();
11     }
12 
13     private static void methodStaticCommon() {
14         System.out.println("AAA");
15         System.out.println("BBB");
16         System.out.println("CCC");
17     }
18 
19 }
代碼示例:解決靜態方法代碼重複問題

接口的使用

接口使用步驟:

1. 接口不能直接使用,必須有一個「實現類」來「實現」該接口。
格式:

1 public class 實現類名稱 implements 接口名稱 {
2     // ...
3 }

2. 接口的實現類必須覆蓋重寫(實現)接口中全部的抽象方法。實現:去掉abstract關鍵字,加上方法體大括號。

3. 建立實現類的對象,進行使用。

常量的使用

接口中的常量使用只須要:接口名.常量名。不須要建立對象

 1 public interface MyInterfaceConst {
 2     // 這其實就是一個常量,一旦賦值,不能夠修改
 3     public static final int NUM_OF_MY_CLASS = 12;
 4 
 5 }
 6 
 7 
 8 --------------------------------------------------------------------------------
 9 public static void main(String[] args) {
10     // 訪問接口當中的常量
11     System.out.println(MyInterfaceConst.NUM_OF_MY_CLASS);
12 }
View Code

默認方法的使用

1. 接口的默認方法,能夠經過接口實現類【對象】,直接調用。

2. 接口的默認方法,也能夠被接口實現類進行覆蓋重寫。

 1 public interface MyInterfaceDefault {
 2     // 默認方法
 3     public default void methodDefault() {
 4         System.out.println("這是默認方法");
 5     }
 6 }
 7 
 8 
 9 
10 ----------------------------------------------------------------
11 // 在實現類中能夠對默認方法進行覆蓋重寫,也能夠什麼操做都不作
12 // 可是若是想使用默認方法必需要有實現類
13 public class MyInterfaceDefaultA implements MyInterfaceDefault {
14     // 能夠對默認方法覆蓋重寫
15 }
16 
17 
18 --------------------------------------------------------------------------
19 public class Demo02Interface {
20 
21     public static void main(String[] args) {
22         // 建立了實現類對象
23         MyInterfaceDefaultA a = new MyInterfaceDefaultA();
24 
25         // 調用默認方法,若是實現類當中沒有,會向上找接口
26         a.methodDefault(); // 這是默認方法
27 
28     }
29 }
View Code

靜態方法的使用

靜態方法的使用:接口名.靜態方法名(參數);

注意:不能經過接口實現類的對象來調用接口當中的靜態方法。

 1 public interface MyInterfaceStatic {
 2 
 3     public static void methodStatic() {
 4         System.out.println("這是接口的靜態方法!");
 5     }
 6 }
 7 
 8 
 9 
10 ------------------------------------------------------------------
11 // 實現類
12 public class MyInterfaceStaticImpl implements MyInterfaceStatic {
13 
14 }
15 
16 
17 ---------------------------------------------------------------------------
18 /*
19 注意事項:不能經過接口實現類的對象來調用接口當中的靜態方法。
20 正確用法:經過接口名稱,直接調用其中的靜態方法。
21 格式:
22 接口名稱.靜態方法名(參數);
23  */
24 public class Demo03Interface {
25 
26     public static void main(String[] args) {
27         // 建立了實現類對象
28         MyInterfaceStaticImpl impl = new MyInterfaceStaticImpl();
29 
30         // 錯誤寫法!
31         // impl.methodStatic();
32 
33         // 直接經過接口名稱調用靜態方法
34         MyInterfaceStatic.methodStatic();
35     }
36 }
View Code

抽象方法的使用

在實現類中覆蓋重寫抽象方法。而後建立實現類【對象】調用實現的方法。

 1 /*
 2 注意事項:
 3 1. 接口當中的抽象方法,修飾符必須是兩個固定的關鍵字:public abstract
 4 2. 這兩個關鍵字修飾符,能夠選擇性地省略。(今天剛學,因此不推薦。)
 5 3. 方法的三要素,能夠隨意定義。
 6  */
 7 public interface MyInterfaceAbstract {
 8 
 9     // 這是一個抽象方法
10     public abstract void methodAbs1();
11 
12     // 這也是抽象方法
13     abstract void methodAbs2();
14 
15     // 這也是抽象方法
16     public void methodAbs3();
17 
18     // 這也是抽象方法
19     void methodAbs4();
20 }
21 
22 
23 -------------------------------------------------------------------------
24 public class MyInterfaceAbstractImpl implements MyInterfaceAbstract {
25     @Override
26     public void methodAbs1() {
27         System.out.println("這是第一個方法!");
28     }
29 
30     @Override
31     public void methodAbs2() {
32         System.out.println("這是第二個方法!");
33     }
34 
35     @Override
36     public void methodAbs3() {
37         System.out.println("這是第三個方法!");
38     }
39 
40     @Override
41     public void methodAbs4() {
42         System.out.println("這是第四個方法!");
43     }
44 }
45 
46 
47 
48 -----------------------------------------------------------------
49 /*
50 注意事項:
51 若是實現類並無覆蓋重寫接口中全部的抽象方法,那麼這個實現類本身就必須是抽象類。
52  */
53 public class Demo01Interface {
54 
55     public static void main(String[] args) {
56         // 錯誤寫法!不能直接new接口對象使用。
57         // MyInterfaceAbstract inter = new MyInterfaceAbstract();
58 
59         // 建立實現類的對象使用
60         MyInterfaceAbstractImpl impl = new MyInterfaceAbstractImpl();
61         impl.methodAbs1();
62         impl.methodAbs2();
63     }
64 }
View Code

注意事項:若是實現類並無覆蓋重寫接口中全部的抽象方法,那麼這個實現類本身就必須是抽象類。

私有方法的使用

普通私有方法:只有在其接口中的默認方法能夠調用。

私有靜態方法:只有在其接口中的默認方法和靜態方法能夠調用。

若是一個接口中有多個默認方法,而且方法中有重複的內容,那麼能夠抽取出來封裝到私有方法中,供默認方法調用。從設計的角度講,私有的方法是對默認方法和靜態方法的輔助

接口的多實現

在繼承體系中,一個類只能繼承一個父類。而對於接口而言,一個類是能夠實現多個接口的,這叫作接口的多實現。而且,一個類能繼承一個父類,同時實現多個接口。

語法

1 class 類名 [extends 父類名] implements 接口名1,接口名2,接口名3... {     
2     // 重寫接口中抽象方法【必須】    
3     // 重寫接口中默認方法【不重名時可選】    
4 }

多實現中的抽象方法

接口中,有多個抽象方法時,實現類必須重寫全部抽象方法若是抽象方法有重名的,只須要重寫一次

 1 public interface MyInterfaceA {
 2 
 3     public abstract void methodA();
 4 
 5     public abstract void methodAbs();
 6 
 7 }
 8 
 9 
10 
11 -------------------------------------------------------
12 public interface MyInterfaceB {
13 
14     public abstract void methodB();
15 
16     public abstract void methodAbs();
17 
18 }
19 
20 
21 
22 ------------------------------------------------------------
23 public class MyInterfaceImpl implements MyInterfaceA, MyInterfaceB {
24     
25     @Override
26     public void methodA() {
27         System.out.println("覆蓋重寫了A方法");
28     }
29 
30 
31     @Override
32     public void methodB() {
33         System.out.println("覆蓋重寫了B方法");
34     }
35 
36     // 重名的只須要重寫一次
37     @Override
38     public void methodAbs() {
39         System.out.println("覆蓋重寫了AB接口都有的抽象方法");
40     }
41 }
View Code

注意:若是實現類沒有覆蓋重寫全部接口當中的全部抽象方法,那麼實現類就必須是一個抽象類。

多實現中的默認方法

接口中,有多個默認方法時,實現類均可繼承使用。不重名的能夠不重寫。若是默認方法有重名的,必須重寫一次。

 1 public interface MyInterfaceA {
 2 
 3     public default void methodDefault() {
 4         System.out.println("默認方法AAA");
 5     }
 6 }
 7 
 8 
 9 
10 ---------------------------------------------------
11 public interface MyInterfaceB {
12 
13     public default void methodDefault() {
14         System.out.println("默認方法BBB");
15     }
16 
17 }
18 
19 
20 
21 -------------------------------------------------------
22 public class MyInterfaceImpl implements MyInterfaceA, MyInterfaceB {
23     // 兩個接口中重名。必須重寫
24     @Override
25     public void methodDefault() {
26         System.out.println("對多個接口當中衝突的默認方法進行了覆蓋重寫");
27     }
28 }
View Code

多實現中的靜態方法

接口中,存在同名的靜態方法並不會衝突,緣由是只能經過各自接口名訪問靜態方法。

優先級問題

一個類若是直接父類當中的方法,和接口當中的默認方法產生了衝突,優先用父類當中的方法。

接口的多繼承

一個接口能繼承另外一個或者多個接口,這和類之間的繼承比較類似。接口的繼承使用 extends 關鍵字,子接口繼承父接口的方法。

 1 // 接口A
 2 public interface MyInterfaceA {
 3 
 4     public abstract void methodA();
 5 
 6     public abstract void methodCommon();
 7 
 8     public default void methodDefault() {
 9         System.out.println("AAA");
10     }
11 }
12 
13 
14 
15 ----------------------------------------------------------
16 // 接口B
17 public interface MyInterfaceB {
18 
19     public abstract void methodB();
20 
21     public abstract void methodCommon();
22 
23     public default void methodDefault() {
24         System.out.println("BBB");
25     }
26 }
27 
28 
29 
30 --------------------------------------------------------------
31 // 繼承接口A和B的接口
32 /*
33 這個子接口當中有幾個方法?答:4個。
34 methodA 來源於接口A
35 methodB 來源於接口B
36 methodCommon 同時來源於接口A和B
37 method 來源於我本身
38  */
39 public interface MyInterface extends MyInterfaceA, MyInterfaceB {
40 
41     public abstract void method();
42 
43     @Override
44     public default void methodDefault() {
45 
46     }
47 }
48 
49 
50 ----------------------------------------------------------------------
51 // 實現類
52 
53 public class MyInterfaceImpl implements MyInterface {
54     @Override
55     public void method() {
56 
57     }
58 
59     @Override
60     public void methodA() {
61 
62     }
63 
64     @Override
65     public void methodB() {
66 
67     }
68 
69     @Override
70     public void methodCommon() {
71 
72     }
73 }
View Code

注意事項:
1. 多個父接口當中的抽象方法若是重複不要緊

2. 多個父接口當中的默認方法若是重複,那麼子接口必須進行默認方法的覆蓋重寫,【並且帶着default關鍵字】。

異常

異常定義

異常 :指的是程序在執行過程當中,出現的非正常的狀況,最終會致使JVM的非正常中止。

在Java等面向對象的編程語言中,異常自己是一個類,產生異常就是建立異常對象並拋出了一個異常對象。Java處理異常的方式是中斷處理。 

注意:異常指的並非語法錯誤,語法錯了,編譯不經過,不會產生字節碼文件,根本不能運行.

異常分類

 異常的根類是java.lang.Throwable,其下有兩個子類:java.lang.Errorjava.lang.Exception日常所說的異常指java.lang.Exception

Error:嚴重錯誤Error,沒法經過處理的錯誤,只能事先避免,比如絕症。

Exception:表示異常,異常產生後程序員能夠經過代碼的方式糾正,使程序繼續運行,是必需要處理的。比如感冒、闌尾炎

Throwable中的經常使用方法:

public void printStackTrace():打印異常的詳細信息。
  包含了異常的類型,異常的緣由,還包括異常出現的位置,在開發和調試階段,都得使用printStackTrace。*

public String getMessage():獲取發生異常的緣由。
  提示給用戶的時候,就提示錯誤緣由。

public String toString():獲取異常的類型和異常描述信息(不用)。

異常處理

拋出異常throw

在java中,提供了一個throw關鍵字,它用來拋出一個指定的異常對象。

  1,建立一個異常對象。封裝一些提示信息(信息能夠本身編寫)。

  2,須要將這個異常對象告知給調用者。怎麼告知呢?怎麼將這個異常對象傳遞到調用者處呢?經過關鍵字throw就能夠完成。throw 異常對象。

語法:

1 throw new 異常類名(參數);
2 示例:
3 throw new NullPointerException("要訪問的arr數組不存在");
4 
5 throw new ArrayIndexOutOfBoundsException("該索引在數組中不存在,已超出範圍");

注意:
1.throw關鍵字必須寫在方法的內部

2.throw關鍵字後邊new的對象必須是Exception或者Exception的子類對象

3.throw關鍵字拋出指定的異常對象,咱們就必須處理這個異常對象
  throw關鍵字後邊建立的是RuntimeException或者是 RuntimeException的子類對象,咱們能夠不處理,默認交給JVM處理(打印異常對象並中斷程序)
  throw關鍵字後邊建立的是編譯異常(寫代碼的時候報錯),咱們就必須處理這個異常,要麼throws,要麼try...catch 

 1 public class Demo03Throw {
 2     public static void main(String[] args) {
 3         //int[] arr = null;
 4         int[] arr = new int[3];
 5         int e = getElement(arr,3);
 6         System.out.println(e);
 7     }
 8     /*
 9         定義一個方法,獲取數組指定索引處的元素
10         參數:
11             int[] arr
12             int index
13         之後(工做中)咱們首先必須對方法傳遞過來的參數進行合法性校驗
14         若是參數不合法,那麼咱們就必須使用拋出異常的方式,告知方法的調用者,傳遞的參數有問題
15         注意:
16             NullPointerException是一個運行期異常,咱們不用處理,默認交給JVM處理
17             ArrayIndexOutOfBoundsException是一個運行期異常,咱們不用處理,默認交給JVM處理
18      */
19     public static int getElement(int[] arr,int index){
20         /*
21             咱們能夠對傳遞過來的參數數組,進行合法性校驗
22             若是數組arr的值是null
23             那麼咱們就拋出空指針異常,告知方法的調用者"傳遞的數組的值是null"
24          */
25         if(arr == null){
26             throw new NullPointerException("傳遞的數組的值是null");
27         }
28 
29         /*
30             咱們能夠對傳遞過來的參數index進行合法性校驗
31             若是index的範圍不在數組的索引範圍內
32             那麼咱們就拋出數組索引越界異常,告知方法的調用者"傳遞的索引超出了數組的使用範圍"
33          */
34         if(index<0 || index>arr.length-1){
35             throw new ArrayIndexOutOfBoundsException("傳遞的索引超出了數組的使用範圍");
36         }
37 
38         int ele = arr[index];
39         return ele;
40     }
41 }
throw代碼示例

源碼中對throw的使用示例:Object中的方法查看引用對象是否爲null

1 //Obects類中的靜態方法
2 //public static <T> T requireNonNull(T obj):查看指定引用對象不是null。
3 源碼:
4 public static <T> T requireNonNull(T obj) {
5     if (obj == null){
6         throw new NullPointerException();
7     }
8     return obj;
9 }
 1 import java.util.Objects;
 2 
 3 public class Demo04Objects {
 4     public static void main(String[] args) {
 5         method(null);
 6     }
 7 
 8     public static void method(Object obj){
 9         //對傳遞過來的參數進行合法性判斷,判斷是否爲null
10         // if(obj == null){
11         //     throw new NullPointerException("傳遞的對象的值是null");
12         // }
13 
14         //Objects.requireNonNull(obj);
15         Objects.requireNonNull(obj,"傳遞的對象的值是null");
16     }
17 }
View Code

聲明異常throws

throws關鍵字:異常處理的第一種方式,交給別人處理

做用:
  當方法內部拋出異常對象的時候,那麼咱們就必須處理這個異常對象
  可使用throws關鍵字處理異常對象,會把異常對象聲明拋出給方法的調用者處理(本身不處理,給別人處理),最終交給JVM處理-->中斷處理

使用格式:(方法聲明的時候使用)

1 修飾符 返回值類型 方法名(參數列表) throws AAAExcepiton,BBBExcepiton...{
2     throw new AAAExcepiton("產生緣由");
3     throw new BBBExcepiton("產生緣由");
4     ...
5 }

注意:
1.throws關鍵字必須寫在方法聲明處

2.throws關鍵字後邊聲明的異常必須是Exception或者是Exception的子類

3.方法內部若是拋出了多個異常對象,那麼throws後邊必須也聲明多個異常
  若是拋出的多個異常對象有子父類關係,那麼直接聲明父類異常便可

4.調用了一個聲明拋出異常的方法,咱們就必須的處理聲明的異常
  1)要麼繼續使用throws聲明拋出,交給方法的調用者處理,最終交給JVM
  2)要麼try...catch本身處理異常

 1 import java.io.FileNotFoundException;
 2 import java.io.IOException;
 3 
 4 public class Demo05Throws {
 5     /*
 6         FileNotFoundException extends IOException extends Excepiton
 7         若是拋出的多個異常對象有子父類關係,那麼直接聲明父類異常便可
 8      */
 9     //public static void main(String[] args) throws FileNotFoundException,IOException {
10     //public static void main(String[] args) throws IOException {
11     public static void main(String[] args) throws Exception {
12         readFile("c:\\a.tx");
13 
14         System.out.println("後續代碼");
15     }
16 
17     /*
18         定義一個方法,對傳遞的文件路徑進行合法性判斷
19         若是路徑不是"c:\\a.txt",那麼咱們就拋出文件找不到異常對象,告知方法的調用者
20         注意:
21             FileNotFoundException是編譯異常,拋出了編譯異常,就必須處理這個異常
22             可使用throws繼續聲明拋出FileNotFoundException這個異常對象,讓方法的調用者處理
23      */
24     public static void readFile(String fileName) throws FileNotFoundException,IOException{
25         if(!fileName.equals("c:\\a.txt")){
26             throw new FileNotFoundException("傳遞的文件路徑不是c:\\a.txt");
27         }
28 
29         /*
30             若是傳遞的路徑,不是.txt結尾
31             那麼咱們就拋出IO異常對象,告知方法的調用者,文件的後綴名不對
32          */
33         if(!fileName.endsWith(".txt")){
34             throw new IOException("文件的後綴名不對");
35         }
36 
37         System.out.println("路徑沒有問題,讀取文件");
38     }
39 }
throws聲明異常代碼示例

try---catch捕獲異常

try...catch:異常處理的第二種方式,本身處理異常

格式:

 1 try{
 2     可能產生異常的代碼
 3 }catch(定義一個異常的變量,用來接收try中拋出的異常對象){
 4     異常的處理邏輯,異常異常對象以後,怎麼處理異常對象
 5     通常在工做中,會把異常的信息記錄到一個日誌中
 6 }
 7 ...
 8 catch(異常類名 變量名){
 9 
10 }

注意:

  1.try中可能會拋出多個異常對象,那麼就可使用多個catch來處理這些異常對象

  2.若是try中產生了異常,那麼就會執行catch中的異常處理邏輯,執行完畢catch中的處理邏輯,繼續執行try...catch以後的代碼
          若是try中沒有產生異常,那麼就不會執行catch中異常的處理邏輯,執行完try中的代碼,繼續執行try...catch以後的代碼

打印錯誤信息的經常使用方法:

public void printStackTrace():打印異常的詳細信息。
  包含了異常的類型,異常的緣由,還包括異常出現的位置,在開發和調試階段,都得使用printStackTrace。*

public String getMessage():獲取發生異常的緣由。
  提示給用戶的時候,就提示錯誤緣由。

public String toString():獲取異常的類型和異常描述信息(不用)。

 1 import java.io.IOException;
 2 
 3 public class Demo01TryCatch {
 4     public static void main(String[] args) {
 5         try{
 6             //可能產生異常的代碼
 7             readFile("d:\\a.tx");
 8             System.out.println("資源釋放");
 9         }catch (IOException e){//try中拋出什麼異常對象,catch就定義什麼異常變量,用來接收這個異常對象
10             //異常的處理邏輯,異常異常對象以後,怎麼處理異常對象
11             //System.out.println("catch - 傳遞的文件後綴不是.txt");
12 
13             /*
14                 Throwable類中定義了3個異常處理的方法
15                  String getMessage() 返回此 throwable 的簡短描述。
16                  String toString() 返回此 throwable 的詳細消息字符串。
17                  void printStackTrace()  JVM打印異常對象,默認此方法,打印的異常信息是最全面的
18              */
19             //System.out.println(e.getMessage());//文件的後綴名不對
20             //System.out.println(e.toString());//重寫Object類的toString java.io.IOException: 文件的後綴名不對
21             //System.out.println(e);//java.io.IOException: 文件的後綴名不對
22 
23 
24             // e.printStackTrace();
25             /*
26                 java.io.IOException: 文件的後綴名不對
27                     at com.itheima.demo02.Exception.Demo01TryCatch.readFile(Demo01TryCatch.java:55)
28                     at com.itheima.demo02.Exception.Demo01TryCatch.main(Demo01TryCatch.java:27)
29              */
30             
31         }
32         System.out.println("後續代碼");
33     }
34 
35     /*
36        若是傳遞的路徑,不是.txt結尾
37        那麼咱們就拋出IO異常對象,告知方法的調用者,文件的後綴名不對
38     */
39     public static void readFile(String fileName) throws IOException {
40 
41         if(!fileName.endsWith(".txt")){
42             throw new IOException("文件的後綴名不對");
43         }
44 
45         System.out.println("路徑沒有問題,讀取文件");
46     }
47 }
48 
49     
View Code

finally代碼塊

finally:有一些特定的代碼不管異常是否發生,都須要執行。另外,由於異常會引起程序跳轉,致使有些語句執行不到。而finally就是解決這個問題的,在finally代碼塊中存放的代碼都是必定會被執行的。

格式:

 1 try{
 2     可能產生異常的代碼
 3 }catch(定義一個異常的變量,用來接收try中拋出的異常對象){
 4     異常的處理邏輯,異常異常對象以後,怎麼處理異常對象
 5     通常在工做中,會把異常的信息記錄到一個日誌中
 6 }
 7 ...
 8 catch(異常類名 變量名){
 9 
10 }finally{
11     不管是否出現異常都會執行
12 }

注意:

  1,finally不能單獨使用,必須和try一塊兒使用

  2,finally通常用於資源釋放(資源回收),不管程序是否出現異常,最後都要資源釋放(IO)

  3,當只有在try或者catch中調用退出JVM的相關方法,此時finally纔不會執行,不然finally永遠會執行

 1 import java.io.IOException;
 2 
 3 public class Demo02TryCatchFinally {
 4     public static void main(String[] args) {
 5         try {
 6             //可能會產生異常的代碼
 7             readFile("c:\\a.tx");
 8         } catch (IOException e) {
 9             //異常的處理邏輯
10             e.printStackTrace();
11         } finally {
12             //不管是否出現異常,都會執行
13             System.out.println("資源釋放");
14         }
15     }
16 
17     /*
18        若是傳遞的路徑,不是.txt結尾
19        那麼咱們就拋出IO異常對象,告知方法的調用者,文件的後綴名不對
20 
21     */
22     public static void readFile(String fileName) throws IOException {
23 
24         if(!fileName.endsWith(".txt")){
25             throw new IOException("文件的後綴名不對");
26         }
27 
28         System.out.println("路徑沒有問題,讀取文件");
29     }
30 }
finally代碼塊示例

異常注意事項

 注意1:多個異常使用捕獲又該如何處理呢?
  1. 多個異常分別處理。
  2. 多個異常一次捕獲,屢次處理。【推薦】
  3. 多個異常一次捕獲一次處理。

 1 import java.util.List;
 2 
 3 public class Demo01Exception {
 4     public static void main(String[] args) {
 5         /*
 6             多個異常使用捕獲又該如何處理呢?
 7             1. 多個異常分別處理。
 8             2. 多個異常一次捕獲,屢次處理。
 9             3. 多個異常一次捕獲一次處理。
10          */
11 
12         //1. 多個異常分別處理。
13        try {
14             int[] arr = {1,2,3};
15             System.out.println(arr[3]);//ArrayIndexOutOfBoundsException: 3
16         }catch (ArrayIndexOutOfBoundsException e){
17             System.out.println(e);
18         }
19 
20         try{
21             List<Integer> list = List.of(1, 2, 3);
22             System.out.println(list.get(3));//IndexOutOfBoundsException: Index 3 out-of-bounds for length 3
23         }catch (IndexOutOfBoundsException e){
24             System.out.println(e);
25         }
26 
27 
28         //2. 多個異常一次捕獲,屢次處理。
29         try {
30             int[] arr = {1,2,3};
31             //System.out.println(arr[3]);//ArrayIndexOutOfBoundsException: 3
32             List<Integer> list = List.of(1, 2, 3);
33             System.out.println(list.get(3));//IndexOutOfBoundsException: Index 3 out-of-bounds for length 3
34         }catch (ArrayIndexOutOfBoundsException e){
35             System.out.println(e);
36         }catch (IndexOutOfBoundsException e){
37             System.out.println(e);
38         }
39 
40         /*
41             一個try多個catch注意事項:
42                 catch裏邊定義的異常變量,若是有子父類關係,那麼子類的異常變量必須寫在上邊,不然就會報錯
43                 ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException
44          */
45         try {
46             int[] arr = {1,2,3};
47             //System.out.println(arr[3]);//ArrayIndexOutOfBoundsException: 3
48             List<Integer> list = List.of(1, 2, 3);
49             System.out.println(list.get(3));//IndexOutOfBoundsException: Index 3 out-of-bounds for length 3
50         }catch (IndexOutOfBoundsException e){
51             System.out.println(e);
52         }catch (ArrayIndexOutOfBoundsException e){
53             System.out.println(e);
54         }
55 
56         //3. 多個異常一次捕獲一次處理。
57         try {
58             int[] arr = {1,2,3};
59             //System.out.println(arr[3]);//ArrayIndexOutOfBoundsException: 3
60             List<Integer> list = List.of(1, 2, 3);
61             System.out.println(list.get(3));//IndexOutOfBoundsException: Index 3 out-of-bounds for length 3
62         }catch (Exception e){
63             System.out.println(e);
64         }
65     }
66 }
代碼示例

注意2:運行時異常被拋出能夠不處理。即不捕獲也不聲明拋出。

默認給虛擬機處理,終止程序,何時不拋出運行時異常了,在來繼續執行程序

 1 import java.util.List;
 2 
 3 public class Demo01Exception {
 4     public static void main(String[] args) {
 5 
 6         //運行時異常被拋出能夠不處理。即不捕獲也不聲明拋出。
 7         //默認給虛擬機處理,終止程序,何時不拋出運行時異常了,在來繼續執行程序
 8         int[] arr = {1,2,3};
 9         System.out.println(arr[3]);//ArrayIndexOutOfBoundsException: 3
10         List<Integer> list = List.of(1, 2, 3);
11         System.out.println(list.get(3));//IndexOutOfBoundsException: Index 3 out-of-bounds for length 3
12 
13         System.out.println("後續代碼!");
14     }
15 }
View Code

注意3:若是finally有return語句,永遠返回finally中的結果,避免該狀況.

 1 public class Demo02Exception {
 2     public static void main(String[] args) {
 3         int a = getA();
 4         System.out.println(a);// 100
 5     }
 6 
 7     //定義一個方法,返回變量a的值
 8     public static int getA(){
 9         int a = 10;
10         try{
11             return a;
12         }catch (Exception e){
13             System.out.println(e);
14         }finally {
15             //必定會執行的代碼
16             a = 100;
17             return a;
18         }
19     }
20 }
View Code

注意4:子父類的異常:

  若是父類拋出了多個異常,子類重寫父類方法時,拋出和父類相同的異常或者是父類異常的子類或者不拋出異常。

  父類方法沒有拋出異常,子類重寫父類該方法時也不可拋出異常。此時子類產生該異常,只能捕獲處理,不能聲明拋出

 1 public class Fu {
 2     public void show01() throws NullPointerException,ClassCastException{}
 3     public void show02() throws IndexOutOfBoundsException{}
 4     public void show03() throws IndexOutOfBoundsException{}
 5     public void show04() throws Exception {}
 6 }
 7 
 8 class Zi extends Fu{
 9     //子類重寫父類方法時,拋出和父類相同的異常
10     public void show01() throws NullPointerException,ClassCastException{}
11 
12     //子類重寫父類方法時,拋出父類異常的子類
13     public void show02() throws ArrayIndexOutOfBoundsException{}
14 
15     //子類重寫父類方法時,不拋出異常
16     public void show03() {}
17 
18     /*
19         父類方法沒有拋出異常,子類重寫父類該方法時也不可拋出異常。
20      */
21     //public void show04() throws Exception{}
22 
23     //此時子類產生該異常,只能捕獲處理,不能聲明拋出
24     public void show04()  {
25         try {
26             throw  new Exception("編譯期異常");
27         } catch (Exception e) {
28             e.printStackTrace();
29         }
30     }
31 }
View Code

自定義異常

爲何要自定義異常:

  咱們說了Java中不一樣的異常類,分別表示着某一種具體的異常狀況,那麼在開發中老是有些異常狀況是SUN沒有定義好的,此時咱們根據本身業務的異常狀況來定義異常類。例如年齡負數問題,考試成績負數問題等等。

什麼是自定義異常類:

  在開發中根據本身業務的異常狀況來定義異常類.

  自定義一個業務邏輯異常: RegisterException。一個註冊異常類。

異常類如何定義:

  自定義一個編譯期異常: 自定義類 並繼承於java.lang.Exception

  自定義一個運行時期的異常類:自定義類 並繼承於java.lang.RuntimeException

 語法:

1 public class XXXExcepiton extends Exception | RuntimeException{
2     添加一個空參數的構造方法
3     添加一個帶異常信息的構造方法
4 }

注意:
  1.自定義異常類通常都是以Exception結尾,說明該類是一個異常類

  2.自定義異常類,必須的繼承Exception或者RuntimeException
    繼承Exception:那麼自定義的異常類就是一個編譯期異常,若是方法內部拋出了編譯期異常,就必須處理這個異常,要麼throws,要麼try...catch
    繼承RuntimeException:那麼自定義的異常類就是一個運行期異常,無需處理,交給虛擬機處理(中斷處理) 

 1 public class RegisterException extends /*Exception*/ RuntimeException{
 2     //添加一個空參數的構造方法
 3     public RegisterException(){
 4         super();
 5     }
 6 
 7     /*
 8         添加一個帶異常信息的構造方法
 9         查看源碼發現,全部的異常類都會有一個帶異常信息的構造方法,方法內部會調用父類帶異常信息的構造方法,讓父類來處理這個異常信息
10      */
11     public RegisterException(String message){
12         super(message);
13     }
14 }
自定義異常類代碼示例

自定義異常的使用語法和系統提供的使用語法相同:

 1 public class RegisterException extends /*Exception*/ RuntimeException{
 2     //添加一個空參數的構造方法
 3     public RegisterException(){
 4         super();
 5     }
 6 
 7     /*
 8         添加一個帶異常信息的構造方法
 9         查看源碼發現,全部的異常類都會有一個帶異常信息的構造方法,方法內部會調用父類帶異常信息的構造方法,讓父類來處理這個異常信息
10      */
11     public RegisterException(String message){
12         super(message);
13     }
14 }
15 
16 
17 ========================================
18 import java.util.Scanner;
19 
20 /*
21     要求:咱們模擬註冊操做,若是用戶名已存在,則拋出異常並提示:親,該用戶名已經被註冊。
22 
23     分析:
24         1.使用數組保存已經註冊過的用戶名(數據庫)
25         2.使用Scanner獲取用戶輸入的註冊的用戶名(前端,頁面)
26         3.定義一個方法,對用戶輸入的中註冊的用戶名進行判斷
27             遍歷存儲已經註冊過用戶名的數組,獲取每個用戶名
28             使用獲取到的用戶名和用戶輸入的用戶名比較
29                 true:
30                     用戶名已經存在,拋出RegisterException異常,告知用戶"親,該用戶名已經被註冊";
31                 false:
32                     繼續遍歷比較
33             若是循環結束了,尚未找到重複的用戶名,提示用戶"恭喜您,註冊成功!";
34  */
35 public class Demo01RegisterException {
36     // 1.使用數組保存已經註冊過的用戶名(數據庫)
37     static String[] usernames = {"張三","李四","王五"};
38 
39     public static void main(String[] args) /*throws RegisterException*/ {
40         //2.使用Scanner獲取用戶輸入的註冊的用戶名(前端,頁面)
41         Scanner sc = new Scanner(System.in);
42         System.out.println("請輸入您要註冊的用戶名:");
43         String username = sc.next();
44         checkUsername(username);
45 
46     }
47 
48     //3.定義一個方法,對用戶輸入的中註冊的用戶名進行判斷
49     public static void checkUsername(String username) /*throws RegisterException*/ {
50         //遍歷存儲已經註冊過用戶名的數組,獲取每個用戶名
51         for (String name : usernames) {
52             //使用獲取到的用戶名和用戶輸入的用戶名比較
53             if(name.equals(username)){
54                 //true:用戶名已經存在,拋出RegisterException異常,告知用戶"親,該用戶名已經被註冊";
55                 try {
56                     throw new RegisterException("親,該用戶名已經被註冊");
57                 } catch (RegisterException e) {
58                     e.printStackTrace();
59                     return; //結束方法
60                 }
61             }
62         }
63         //若是循環結束了,尚未找到重複的用戶名,提示用戶"恭喜您,註冊成功!";
64         System.out.println("恭喜您,註冊成功!");
65     }
66 }
自定義異常使用

 

 

 

 

 

 

 

 

------------------------------

相關文章
相關標籤/搜索