1. 程式人生 > >JAVA高階應用之異常類處理

JAVA高階應用之異常類處理

異常分類

Throwable(異常最頂端的類)
    Error(伺服器奔潰 資料庫奔潰)
    Exception(異常類)
        RunTimeException

解決異常

1.出現異常 找上級去解決
2.找上級去解決 相當於找任務的呼叫者 mian的呼叫者 JVM去處理
3.JVM預設的處理方式
        列印異常類 錯誤資訊 和 錯誤發生的位置
        直接停止程式

程式碼示例

public class Demo01{
    public static void main(String[] args){
        int[] array = new
int[3]; // 角標越界異常 ArrayIndexOutOfBoundsException System.out.println(array[6]); // 空指標異常 NullPointException array = null; System.out.println(array.length); // 算術異常 ArithmeticException System.out.println(10/0); } }

寫法

try....catch....finally
try
指測試異常程式碼 catch 指捕獲異常資訊 finally 指異常結束後要做的事

處理異常的流程

1.函式中 某句程式碼發生異常
2.發生異常 會產生對應的異常物件
3.這個異常物件 返回給呼叫者
        情況1:沒有對異常進行處理 這時就會把異常交給上級
              交給JVM去處理 JVM使用了預設的處理機制
        情況2:呼叫者進行了異常處理(try....catch) 這時返回的
              異常物件 會跟catch進行匹配 匹配成功執行catch中的語句
              程式繼續執行

程式碼示例

public
class Demo02{ public static void main(String[] args){ Fun test = new Fun(); try{ int num = test.fun(10,0); System.out.println(num); }catch(ArithmeticException e){ // 小括號中要放捕獲什麼異常 System.out.println("除數不能為0"); } System.out.println("你猜猜我執行了嗎"); } } class Fun{ // 發生異常 一定會產生一個對應的異常物件 public void fun(int a, int b){ // new ArithmeticException("/ by zero") return a/b; } }

結果

除數不能為0
你猜猜我執行了嗎

多catch處理異常

public class Demo03{
    public static void main(String[] args){
        int[] array = new int[4];
        try{
            // 報的越界異常 產生了越界異常的物件
            // new ArrayIndexOutOfBoundsException("5");
            System.out.println(array[5]);
            array = null;
            // 報的空指標異常 產生了空指標異常物件
            // new NullPointException()
            System.out.println(arr.length);
            // 10/0 報運算異常
            // new ArithmeticException()
            System.out.println(10/0);
        }catch(ArrayIndexOutOfBoundsException e){
            System.out.println("下標不能越界");
        }catch(NullPointException e){
            System.out.println("空指標異常 ");
        }catch(ArithmeticException e){
            System.out.println("出現算術錯誤 你除0了");
        }   
        System.out.println(你猜猜我運行了嗎);
    }
}

結果分析

每當出現異常時 便會返回一個異常物件,與catch中的引用進行比對 ,遇到相應的引用,
便會執行其中的語句,其餘的catch不會執行,之後會列印"你猜猜我運行了嗎"

Finally

finally(遺言)
出現異常與否不會影響到finally的執行
也就是說finally一定會執行
finally作用:一般用來關閉資源 關閉流 關閉資料庫

final finally finalize 的區別? 雷鋒和雷峰塔的區別
final(絕育)
finally(遺言) 異常處理時候使用 不能單獨使用
finalize() 是個方法 是做垃圾回收的時候用 系統自己呼叫

安卓開發
客戶端開發 直接使用Exception e 來接收異常

JavaEE開發
伺服器開發 一般會把異常 記錄下來 寫成錯誤日誌 回頭檢視
如果不記錄 相當於把這個錯誤遺漏過去

程式碼示例

public class Demo04{
    public static void main(String[] args){

    try{
        System.out.println(10/0);
        // 即使你直接return方法 finally也會執行
        // 直接關閉JVM 虛擬機器關了 就不執行了
        return;
        // System.exit(0);
    }catch(Exception e){
        System.out.println("不能除以0");
    }finally{
        System.out.println("我要工資破萬");
    }
    System.out.println("你猜猜我執行了嗎");
}

輸出結果

不能除以0
我要工資破萬
你猜猜我執行了嗎

程式碼示例

class TestFinally{
    public int fun(){
        int num = 10;
        try{
            num = 20;
            System.out.println(11/0);
            return num;
        }catch(Exception){
            num = 30;
            return num;
        }finally{
            num = 40;
            // finally中只寫關閉資源 在這裡新增return沒有意義
        }

    }
}

輸出結果

30
解釋:
return相當於建立一個返回路徑 相當於有一個箱子 箱子裡儲存的是
要返回的值 不會馬上return返回 會看一下有沒有finally 但是不會因為後面的finall而更改已經在返回路徑中的值 
等finally執行完了 再完成return

執行異常與變異異常

執行時異常 -- 程式設計師犯的錯
編譯時異常 -- 為了錯誤做的提前準備
public class Demo05{
    public static void main(String[] args){
        try{
            FileInputStream inputStream = new FileInputStream("as.txt");
        }catch(FileNotFoundException e){
            System.out.println("兄弟 你沒有這個檔案");
        }

    }
}

理解

讀取該路徑下的檔案
系統不知道你這個路徑有沒有問題
需要提前詢問你這個路徑有沒有問題
需要提前詢問一下 如果沒有這個路徑下的檔案
編譯時異常 是系統強制你要處理
處理方式1:新增try...catch(自己來處理)
處理方式2:可以把異常拋給上級去處理(這時和自己就沒有關係了)
可以把問題拋給main函式 在main函式的函式宣告上新增
throws 要丟擲異常型別名

自定義異常

 * 需求:
 * 建立一個人類 有name 和 age
 * 要求 人類的年齡賦值時 要在 0120歲之前
 * 不用異常
package com.lanou3g;

public class Demo06 {
    public static void main(String[] args) {
        Person person = new Person();
        person.setName("dp");
        try {
            person.setAge(150);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            System.out.println("賦值年齡超出範圍");
        }
        System.out.println(person);
    }
}
class Person{
    private String name;
    private int age;
    public Person() {
        super();
        // TODO Auto-generated constructor stub
    }
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    // throws 關鍵詞在方法的宣告上 標示這個方法可能會出現異常
    // 誰呼叫這個方法 這個異常就拋給了
    public void setAge(int age) throws Exception{
        // 需要在這個範圍內 給名字賦值
        if(age <= 120 && age >= 0) {
            this.age = age;         
        }else {
            // 丟擲一個異常
            // throw 後面跟的是 丟擲的異常物件
            //Exception e = new Exception("兄弟 你是龜仙人嗎");
            //throw  new Exception("兄弟 你是龜仙人嗎");

            // 丟擲自定義異常
            throw new AgeOutOfBoundsException("兄弟 你是龜仙人嗎");
        }
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }

}

// 自定義異常
// 重點 要見名知意 並且跟系統學習
class AgeOutOfBoundsException extends Exception{

    /*
     * 序列化時 使用的ID
     */
    private static final long serialVersionUID = 1L;

    public AgeOutOfBoundsException() {
        super();
        // TODO Auto-generated constructor stub
    }

    public AgeOutOfBoundsException(String message) {
        super(message);
        // TODO Auto-generated constructor stub
    }
    // 寫有參和無參的構造方法

}

Throwable中的方法

public class Demo07{
    public static void main(String[] args){
        Exception e = new Exception("這裡可以輸出錯誤資訊");
        // 獲取錯誤資訊
        String message = e.getMessage();
        System.out.println(message); //輸出:這裡可以輸出錯誤資訊
        System.out.println(e); //輸出:java.lang.Exception: 這裡可以寫錯誤資訊
        // 列印錯誤資訊 錯誤位置 異常類的類名
        e.printStackTrace(); //輸出:java.lang.Exception: 這裡可以寫錯誤資訊
    at com.lanou3g.Demo07.main(Demo07.java:7)

    }
}

示例:

需求:
// 無限輸入整數 存放到集合中 列印 輸入quit停止
// 希望在輸入字串的時候 讓程式也能繼續執行
package com.lanou3g;

import java.util.ArrayList;
import java.util.Scanner;

public class Demo08 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        ArrayList<Integer>  list = new ArrayList<>();
        while(true) {
            System.out.println("請輸入整數,輸入quit 退出");
            String string = scanner.nextLine();
            if(string.equals("quit")) {
                break;
            }       
            try {           
                int parseInt = Integer.parseInt(string);
                list.add(parseInt);
            } catch (Exception e) {
                System.out.println("你輸入錯誤 重新來吧");
            }

        }
        System.out.println(list);
    }
}