首頁  >  文章  >  Java  >  Java異常的處理方式有哪些

Java異常的處理方式有哪些

PHPz
PHPz轉載
2023-05-25 15:40:562109瀏覽

什麼是異常?

異常在我們寫程式碼是特別常見,因為程式設計師大部分時間都在修復bug,在java中透過throwable頂層類別又可以分為兩個,一個是Error(錯誤),一個是Exception (異常)。

Java異常的處理方式有哪些

Error(錯誤) : Error與例外不同的是,錯誤並不能處理,而是程式設計師造成的問題,例如文法錯誤那就要程式設計師檢查自己的語法,例如結果錯誤(StackOverflowError和OutOfMemoryError

),那就要程式設計師檢查自己的邏輯。

Exception(異常) : 這個可以用一些方式來處理,例如我們後面要講的throws(聲明異常),try{}catch{}(處理異常)這都是我們處理異常的方式,而異常又分為受查異常(編譯時異常)和非受查異常(運行時異常RuntimeException)。

編譯時異常:程式不能通過編譯,就是編譯時異常,例如:clone時必須要透過throws來宣告異常

執行時異常:指的是程式能通過編譯,但是運轉時出現異常。例如:NullPointerException、

拋出的異常為ArrayIndexOutOfBoundsException或ArithmeticException。

以上的異常我們都能進行處理解決,但是錯誤需要程式設計師自己檢查程式碼。

異常的處理

我們有兩種方式來進行處理:

一種是事前防禦型:

boolean ret = false;
ret = 登陸遊戲();
if (!ret) {
處理登陸遊戲錯誤;
return;
} r
et = 開始符合();
if (!ret) {
處理匹配錯誤;
return;
} r
et = 遊戲確認();
if (!ret) {
處理遊戲確認錯誤;
return;
} r
et = 選擇英雄();
if (!ret) {
處理選擇英雄錯誤;
return;
} r
et = 載入遊戲畫面();
if (!ret) {
處理載入遊戲錯誤;
return;
} .
.....

#事前防禦型就是每一步都要檢查是否出現了錯誤,這樣的缺點就是程式碼顯得很混亂,效率低;

一種是事後認錯型:

try {
登陸遊戲();
開始符合();
遊戲確認();
選擇英雄();
載入遊戲畫面();
...
} catch (登陸遊戲異常) {
處理登陸遊戲異常;
} catch (開始匹配異常) {
處理開始匹配異常;
} catch (遊戲確認異常) {
處理遊戲確認異常;
} catch (選擇英雄異常) {
處理選擇英雄異常;
} catch (載入遊戲畫面異常) {
處理載入遊戲畫面異常;
} .
....

這種做法就是將所有程式碼可能出現的例外值全部放在try裡,如果發現異常正在進行捕獲,這種就是先進行操作遇到問題在進行處理。

我們常常使用第二種trycatch這樣讓程式碼簡潔,清晰,效率更高。

異常的拋出

如果某段程式碼不符合預期,我們需要使用Java中的throw關鍵字來拋出例外。

語法是  throw new 例外(你要拋出的例外)

public class TestDemo {
    public static void func(int a) {
        if(a==10) {
            throw new RuntimeException("a==10不符合预期,抛出这个异常");
        }
    }
    public static void main(String[] args) {
           func(10);
    }
}

看這段程式碼:例如我們10這個數字不符合我們程式的預期,所以要拋出例外,我們就可以這樣跑出: throw new RuntimeException("a==10不符合預期,拋出這個異常");

處理異常

我們通常有兩種方式來處理異常,一種是透過throws聲明異常,一種是透過try{}catch{}透過try檢查程式碼區塊裡是否有異常,如果有異常catch就進行捕獲,如果沒有異常就正常下面的程式碼。

throws聲明異常

語法:throws 異常,異常,異常......(可聲明多個異常)

public class TestDemo {
    public static void function(int[] array) {
        System.out.println(array[100]);
    }
    public static void main(String[] args) {
        int[] array = {7, 8, 9, 5, 6};
        function(array);
    }
}

大家都知道這裡訪問100下標是數組越界異常:

Java異常的處理方式有哪些

接下來透過throws來宣告例外:

Java異常的處理方式有哪些

##還是會報錯。

當我們也給主函數宣告一個例外:

Java異常的處理方式有哪些

 答案還是會錯誤。

所以從這裡我們得出了一個結論:透過throws只是告訴編譯器,這個方法可能會發生這個異常,只是聲明,但是並沒有進行處理異常。我們也可以發現,如果某一個方法出現了異常,那就會看這個方法有沒有處理異常,如果沒有處理就去看上層呼叫者有沒有處理異常。這裡就是func只是宣告了異常,並沒有進行處理異常,然後去上層呼叫者有沒有處理異常(也就是main方法)還是沒有處理異常,最後就交給JVM來處理進行終止程序。異常聲明必須為 Exception 類別或其子類別。

要处理异常,就需要使用接下来所述的try{}catch语句。

捕获异常

try{

}catch(){

}

在Java我们利用try{}catch{}来处理异常;

语法:

    try{
     //可能发生异常的代码
    }catch(异常 变量){//例如:ArrayIndexOutOfBoundsException(要捕获的异常) e(变量)
      //如果try中的代码抛出异常了,此处catch捕获时异常类型与try中抛出的异常类型一致时,
      //或者是try中抛出异常的基类时,就会被捕获到
      // 对异常就可以正常处理,处理完成后,跳出try-catch结构,继续执行后序代码
    }finally{
      //此处代码一定会执行,用于资源清理扫尾等工作
    }

我们先来讲一下try{}catch(){}

/*在方法中处理异常*/
public class TestDemo {
    public static void function(int[] array) throws ArrayIndexOutOfBoundsException {
        try{
            System.out.println(array[100]);
        }catch(ArrayIndexOutOfBoundsException e) {
            System.out.println("array[100]->数组下标越界异常catch->捕获成功");
        }
    }
    public static void main(String[] args) throws ArrayIndexOutOfBoundsException {
        int[] array = {7, 8, 9, 5, 6};
        function(array);
    }
}
/*在main方法中处理异常*/
public class TestDemo {
    public static void function(int[] array) throws ArrayIndexOutOfBoundsException {
            System.out.println(array[100]);
    }
    public static void main(String[] args) throws ArrayIndexOutOfBoundsException {
        int[] array = {7, 8, 9, 5, 6};
        try{
            function(array);
        }catch(ArrayIndexOutOfBoundsException e) {
            System.out.println("array[100]->数组下标越界异常catch->捕获成功");
        }
    }
}

我们使用try{}catch(){}就可以对异常进行处理,既可以在方法中处理异常也可以在main方法中处理异常,同时这里throws虽然没有什么用处,但是可以清晰的告诉程序员,这个方法未来可能会发生这个异常,所以还是有必要的。

try{}catch{}注意点 一:

Java異常的處理方式有哪些

Java異常的處理方式有哪些

当捕获异常成功的时候,后面的业务代码正常执行,如果没有捕获那就不会执行。

try{}catch{}注意点 二:

Java異常的處理方式有哪些

 当try里检查到异常,catch就会捕获,计算这个异常后面还有异常也不会执行。

try{}catch{}注意点三:

throws只是声明异常,并没有处理异常,我们要通过try{}catch(){}来处理异常。

try{}catch{}注意点四:

Java異常的處理方式有哪些

 当catch捕获的异常类型与发生异常类型不符合,就不会被捕获,就继续往外抛异常知道JVM收到后终止程序

try{}catch{}注意点五:

Java異常的處理方式有哪些

 当发生多种异常的时候,那就要多种catch来捕获,多种异常,多次捕获。

try{}catch{}注意点六:

Java異常的處理方式有哪些

 Exception是所有类的父类不能在前面捕获,而是应该放在最末尾进行收尾工作。

既然Exception类是所对应异常类的父类,那可不可以捕获Exception,即多次异常,一次捕获呢??

catch 进行类型匹配的时候, 不光会匹配相同类型的异常对象, 也会捕捉目标异常类型的子类对象

答案是不建议的。当代码变得复杂时,只捕获Exception类并不能明确哪些处理方式出现了问题。

打印异常信息

Java異常的處理方式有哪些

我们还可以利用printStackTrace来打印错误信息。

finally:

finally经常与try{}catch(){}进行一起使用,finally主要是进行资源的清理,的扫尾工作,且finally一定会被执行。

Java異常的處理方式有哪些

Java異常的處理方式有哪些

我们来看这样一段代码结果会是什么??

public class TestDemo {
    public static int function(int[] array) throws ArrayIndexOutOfBoundsException {
        try {
            System.out.println(array[100]);
        }catch(ArrayIndexOutOfBoundsException e) {
            System.out.println("array[100]->数组下标越界异常catch->捕获成功");
            return -1;
        }finally{
            System.out.println("finally主要进行资源回收和清理的扫尾工作~~~");
            return 9;
        }
    }
    public static void main(String[] args) throws ArrayIndexOutOfBoundsException,ArithmeticException {
        int[] array = {7, 8, 9, 5, 6};
        System.out.println(function(array));
        System.out.println("以下是业务代码~~~~~~");
    }
}

Java異常的處理方式有哪些

 答案并不是我们想的return-1,执行结束,而是return9,我们这里可以理解为finally的9将catch里的-1覆盖。所以finally里面的代码是一定会执行的。

异常的处理流程

我的理解:

第一步检查try里面的代码里是否有异常,如果有异常catch就进行捕获,如果没有异常接着往下执行,这里catch如果没有捕获到就看一看上层调用者有没有处理,有处理就进行处理,没有处理就交给JVM终止程序。如果catch捕获到了,下面正常的业务代码正常执行。无论catch是否捕获到异常,finally代码块都将被执行。

官方:

  • 程序先执行 try 中的代码

  • 如果 try 中的代码出现异常, 就会结束 try 中的代码, 看和 catch 中的异常类型是否匹配.

  • 如果找到匹配的异常类型, 就会执行 catch 中的代码

  • 如果没有找到匹配的异常类型, 就会将异常向上传递到上层调用者.

  • 无论是否找到匹配的异常类型, finally 中的代码都会被执行到(在该方法结束之前执行).

  • 如果上层调用者也没有处理的了异常, 就继续向上传递.

  • 一直到 main 方法也没有合适的代码处理异常, 就会交给 JVM 来进行处理, 此时程序就会异常终止。

自定义异常

在我们做很大型的项目的时候,我们就会发现,我们遇到的异常,在Java中的内置异常并没有,所以我们就需要自己定义一个异常,来维护我们实际中遇到的异常。

java 中虽然已经内置了丰富的异常类, 但是并不能完全表示实际开发中所遇到的一些异常,此时需要维护符合我们实际情况的异常结构

在Java中自己声明异常,不是说你写了个异常的名字就是一个异常,而是在你自己定义的异常需要取继承原有的内置异常。

我们通过一个登陆的代码来讲解自定义异常:

class LogIn {
    private String name ="Admin";//用户名
    private String password= "CsDn1263987..0";
    public void logInFor(String name,String password) throws UserNameErrorExecption, PasswordErrorException {
        if(!this.name.equals(name)){
            throw new UserNameErrorExecption("用户名参数异常!!!");
        }
        if(!this.password.equals(password)) {
            throw  new PasswordErrorException("用户密码参数异常!!!");
        }
        System.out.println("~~~登陆成功~~~");
    }
}
public class TestDemo{
    public static void main(String[] args) throws UserNameErrorExecption, PasswordErrorException {
        LogIn logIn = new LogIn();
        //logIn.logInFor("Admin","CsDn1263987..0");
        try{
            logIn.logInFor("Admin","CsDn126398..0");
        }catch(UserNameErrorExecption nameError) {
            nameError.printStackTrace();
            System.out.println("用户名错误!!!");
        }catch(PasswordErrorException passwordError) {
            passwordError.printStackTrace();
            System.out.println("密码错误!!!");
        }
    }
}

自定义异常:

class PasswordError extends Exception {
     public PasswordError(String message) {
           super(message);
     }
}
class UserNameError extends Exception {
    public UserNameError(String message) {
        super(message);
    }
}

这就是我们定义的两个异常。

通过继承Exception来定义两个异常。

通常我们自定义异常类要继承Exception或者RunTimeException类,除此之外也可以定义其他类作为异常类。

  • 自定义异常通常会继承自 Exception 或者 RuntimeException

  • 继承自 Exception 的异常默认是受查异常

  • 继承自 RuntimeException 的异常默认是非受查异常

以上是Java異常的處理方式有哪些的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除