溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

Java異常的處理方式有哪些

發(fā)布時(shí)間:2022-04-25 16:19:18 來(lái)源:億速云 閱讀:192 作者:iii 欄目:開(kāi)發(fā)技術(shù)

這篇文章主要介紹“Java異常的處理方式有哪些”的相關(guān)知識(shí),小編通過(guò)實(shí)際案例向大家展示操作過(guò)程,操作方法簡(jiǎn)單快捷,實(shí)用性強(qiáng),希望這篇“Java異常的處理方式有哪些”文章能幫助大家解決問(wèn)題。

什么是異常?

異常在我們寫(xiě)代碼是特別常見(jiàn),因?yàn)槌绦騿T大部分時(shí)間都在修復(fù)bug,在java中通過(guò)throwable頂層類(lèi)又可以分為兩個(gè),一個(gè)是Error(錯(cuò)誤),一個(gè)是Exception(異常)。

Java異常的處理方式有哪些

Error(錯(cuò)誤) : Error與異常不同的是,錯(cuò)誤并不能處理,而是程序員造成的問(wèn)題,比如語(yǔ)法錯(cuò)誤那就要程序員檢查自己的語(yǔ)法,比如結(jié)果錯(cuò)誤(StackOverflowError和OutOfMemoryError

),那就要程序員檢查自己的邏輯。

Exception(異常) : 這個(gè)可以通過(guò)一些方式來(lái)處理,比如我們后面要講的throws(聲明異常),try{}catch{}(處理異常)這都是我們處理異常的方式,而異常又分為受查異常(編譯時(shí)異常)和非受查異常(運(yùn)行時(shí)異常RuntimeException)。

編譯時(shí)異常:程序不能通過(guò)編譯,就是編譯時(shí)異常,比如:clone時(shí)必須要通過(guò)throws來(lái)聲明異常

運(yùn)行時(shí)異常:指的是程序能通過(guò)編譯,但是運(yùn)行時(shí)出現(xiàn)異常。比如:NullPointerException、

ArrayIndexOutOfBoundsException、ArithmeticException。

以上的異常我們都能進(jìn)行處理解決,但是錯(cuò)誤需要程序員自己檢查代碼。

異常的處理

我們有兩種方式來(lái)來(lái)進(jìn)行處理:

一種是事前防御型:

boolean ret = false;
ret = 登陸游戲();
if (!ret) {
處理登陸游戲錯(cuò)誤;
return;
} r
et = 開(kāi)始匹配();
if (!ret) {
處理匹配錯(cuò)誤;
return;
} r
et = 游戲確認(rèn)();
if (!ret) {
處理游戲確認(rèn)錯(cuò)誤;
return;
} r
et = 選擇英雄();
if (!ret) {
處理選擇英雄錯(cuò)誤;
return;
} r
et = 載入游戲畫(huà)面();
if (!ret) {
處理載入游戲錯(cuò)誤;
return;
} .
.....

事前防御型就是每一步都要檢查是否出現(xiàn)了錯(cuò)誤,這樣的缺點(diǎn)就是代碼顯得很混亂,效率低下;

一種是事后認(rèn)錯(cuò)型:

try {
登陸游戲();
開(kāi)始匹配();
游戲確認(rèn)();
選擇英雄();
載入游戲畫(huà)面();
...
} catch (登陸游戲異常) {
處理登陸游戲異常;
} catch (開(kāi)始匹配異常) {
處理開(kāi)始匹配異常;
} catch (游戲確認(rèn)異常) {
處理游戲確認(rèn)異常;
} catch (選擇英雄異常) {
處理選擇英雄異常;
} catch (載入游戲畫(huà)面異常) {
處理載入游戲畫(huà)面異常;
} .
....

這種做法就是將所有代碼可能出現(xiàn)的異常全部放在try里,如果發(fā)現(xiàn)異常在進(jìn)行捕獲,這種就是先進(jìn)行操作遇到問(wèn)題在進(jìn)行處理。

我們常常使用第二種trycatch這樣使代碼簡(jiǎn)潔,清晰,效率更高。

異常的拋出

如果哪段代碼不符合你的預(yù)期,這段代碼我們就要拋出異常,java中我們通過(guò)關(guān)鍵字throw來(lái)拋出異常。

語(yǔ)法是  throw new 異常(你要拋出的異常)

public class TestDemo {
    public static void func(int a) {
        if(a==10) {
            throw new RuntimeException("a==10不符合預(yù)期,拋出這個(gè)異常");
        }
    }
    public static void main(String[] args) {
           func(10);
    }
}

看這段代碼:比如我們10這個(gè)數(shù)字不符合我們程序的預(yù)期,所以要拋出異常,我們就可以這樣跑出: throw new RuntimeException("a==10不符合預(yù)期,拋出這個(gè)異常");

處理異常

我們通常有兩種方式來(lái)處理異常,一種是通過(guò)throws聲明異常,一種是通過(guò)try{}catch{}通過(guò)try檢查代碼塊里是否有異常,如果有異常catch就進(jìn)行捕獲,如果沒(méi)有異常就正常下面的代碼。

throws聲明異常

語(yǔ)法:throws 異常,異常,異常......(可聲明多個(gè)異常)

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);
    }
}

大家都知道這里訪(fǎng)問(wèn)100下標(biāo)是數(shù)組越界異常:

Java異常的處理方式有哪些

接下來(lái)通過(guò)throws來(lái)聲明異常:

Java異常的處理方式有哪些

還是會(huì)報(bào)錯(cuò)。

當(dāng)我們也給主函數(shù)聲明異常:

Java異常的處理方式有哪些

 答案依然會(huì)報(bào)錯(cuò)。

所以從這里我們得出了一個(gè)結(jié)論:通過(guò)throws只是告訴編譯器,這個(gè)方法可能會(huì)發(fā)生這個(gè)異常,只是聲明,但是并沒(méi)有進(jìn)行處理異常。我們還可以發(fā)現(xiàn),如果某一個(gè)方法出現(xiàn)了異常,那就會(huì)看這個(gè)方法有沒(méi)有處理異常,如果沒(méi)有處理就去看一看上層調(diào)用者有沒(méi)有處理異常。這里就是func只是聲明了異常,并沒(méi)有進(jìn)行處理異常,然后去上層調(diào)用者有沒(méi)有處理異常(也就是main方法)還是沒(méi)有處理異常,最后就交給JVM來(lái)處理進(jìn)行終止程序。聲明的異常必須是 Exception 或者 Exception 的子類(lèi)。

那怎么進(jìn)行處理異常呢??  那就要通過(guò)我們接下來(lái)講解的try{}catch來(lái)進(jìn)行處理異常。

捕獲異常

try{

}catch(){

}

在Java我們利用try{}catch{}來(lái)處理異常;

語(yǔ)法:

    try{
     //可能發(fā)生異常的代碼
    }catch(異常 變量){//例如:ArrayIndexOutOfBoundsException(要捕獲的異常) e(變量)
      //如果try中的代碼拋出異常了,此處catch捕獲時(shí)異常類(lèi)型與try中拋出的異常類(lèi)型一致時(shí),
      //或者是try中拋出異常的基類(lèi)時(shí),就會(huì)被捕獲到
      // 對(duì)異常就可以正常處理,處理完成后,跳出try-catch結(jié)構(gòu),繼續(xù)執(zhí)行后序代碼
    }finally{
      //此處代碼一定會(huì)執(zhí)行,用于資源清理掃尾等工作
    }

我們先來(lái)講一下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]->數(shù)組下標(biāo)越界異常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]->數(shù)組下標(biāo)越界異常catch->捕獲成功");
        }
    }
}

我們使用try{}catch(){}就可以對(duì)異常進(jìn)行處理,既可以在方法中處理異常也可以在main方法中處理異常,同時(shí)這里throws雖然沒(méi)有什么用處,但是可以清晰的告訴程序員,這個(gè)方法未來(lái)可能會(huì)發(fā)生這個(gè)異常,所以還是有必要的。

try{}catch{}注意點(diǎn) 一:

Java異常的處理方式有哪些

Java異常的處理方式有哪些

當(dāng)捕獲異常成功的時(shí)候,后面的業(yè)務(wù)代碼正常執(zhí)行,如果沒(méi)有捕獲那就不會(huì)執(zhí)行。

try{}catch{}注意點(diǎn) 二:

Java異常的處理方式有哪些

 當(dāng)try里檢查到異常,catch就會(huì)捕獲,計(jì)算這個(gè)異常后面還有異常也不會(huì)執(zhí)行。

try{}catch{}注意點(diǎn)三:

throws只是聲明異常,并沒(méi)有處理異常,我們要通過(guò)try{}catch(){}來(lái)處理異常。

try{}catch{}注意點(diǎn)四:

Java異常的處理方式有哪些

 當(dāng)catch捕獲的異常類(lèi)型與發(fā)生異常類(lèi)型不符合,就不會(huì)被捕獲,就繼續(xù)往外拋異常知道JVM收到后終止程序

try{}catch{}注意點(diǎn)五:

Java異常的處理方式有哪些

 當(dāng)發(fā)生多種異常的時(shí)候,那就要多種catch來(lái)捕獲,多種異常,多次捕獲。

try{}catch{}注意點(diǎn)六:

Java異常的處理方式有哪些

 Exception是所有類(lèi)的父類(lèi)不能在前面捕獲,而是應(yīng)該放在最末尾進(jìn)行收尾工作。

既然Exception類(lèi)是所對(duì)應(yīng)異常類(lèi)的父類(lèi),那可不可以捕獲Exception,即多次異常,一次捕獲呢??

catch 進(jìn)行類(lèi)型匹配的時(shí)候, 不光會(huì)匹配相同類(lèi)型的異常對(duì)象, 也會(huì)捕捉目標(biāo)異常類(lèi)型的子類(lèi)對(duì)象

答案是不建議的。因?yàn)楫?dāng)代碼進(jìn)行復(fù)雜的時(shí)候,只捕獲Exception類(lèi)并不知道究竟是什么處理出了問(wèn)題。

打印異常信息

Java異常的處理方式有哪些

我們還可以利用printStackTrace來(lái)打印錯(cuò)誤信息。

finally:

finally經(jīng)常與try{}catch(){}進(jìn)行一起使用,finally主要是進(jìn)行資源的清理,的掃尾工作,且finally一定會(huì)被執(zhí)行。

Java異常的處理方式有哪些

Java異常的處理方式有哪些

我們來(lái)看這樣一段代碼結(jié)果會(huì)是什么??

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]->數(shù)組下標(biāo)越界異常catch->捕獲成功");
            return -1;
        }finally{
            System.out.println("finally主要進(jìn)行資源回收和清理的掃尾工作~~~");
            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("以下是業(yè)務(wù)代碼~~~~~~");
    }
}

Java異常的處理方式有哪些

 答案并不是我們想的return-1,執(zhí)行結(jié)束,而是return9,我們這里可以理解為finally的9將catch里的-1覆蓋。所以finally里面的代碼是一定會(huì)執(zhí)行的。

異常的處理流程

我的理解:

第一步檢查try里面的代碼里是否有異常,如果有異常catch就進(jìn)行捕獲,如果沒(méi)有異常接著往下執(zhí)行,這里catch如果沒(méi)有捕獲到就看一看上層調(diào)用者有沒(méi)有處理,有處理就進(jìn)行處理,沒(méi)有處理就交給JVM終止程序。如果catch捕獲到了,下面正常的業(yè)務(wù)代碼正常執(zhí)行。最后無(wú)論catch是否捕獲到了異常,finally里面的代碼都會(huì)執(zhí)行。

官方:

  • 程序先執(zhí)行 try 中的代碼

  • 如果 try 中的代碼出現(xiàn)異常, 就會(huì)結(jié)束 try 中的代碼, 看和 catch 中的異常類(lèi)型是否匹配.

  • 如果找到匹配的異常類(lèi)型, 就會(huì)執(zhí)行 catch 中的代碼

  • 如果沒(méi)有找到匹配的異常類(lèi)型, 就會(huì)將異常向上傳遞到上層調(diào)用者.

  • 無(wú)論是否找到匹配的異常類(lèi)型, finally 中的代碼都會(huì)被執(zhí)行到(在該方法結(jié)束之前執(zhí)行).

  • 如果上層調(diào)用者也沒(méi)有處理的了異常, 就繼續(xù)向上傳遞.

  • 一直到 main 方法也沒(méi)有合適的代碼處理異常, 就會(huì)交給 JVM 來(lái)進(jìn)行處理, 此時(shí)程序就會(huì)異常終止。

自定義異常

在我們做很大型的項(xiàng)目的時(shí)候,我們就會(huì)發(fā)現(xiàn),我們遇到的異常,在Java中的內(nèi)置異常并沒(méi)有,所以我們就需要自己定義一個(gè)異常,來(lái)維護(hù)我們實(shí)際中遇到的異常。

java 中雖然已經(jīng)內(nèi)置了豐富的異常類(lèi), 但是并不能完全表示實(shí)際開(kāi)發(fā)中所遇到的一些異常,此時(shí)需要維護(hù)符合我們實(shí)際情況的異常結(jié)構(gòu)

在Java中自己聲明異常,不是說(shuō)你寫(xiě)了個(gè)異常的名字就是一個(gè)異常,而是在你自己定義的異常需要取繼承原有的內(nèi)置異常。

我們通過(guò)一個(gè)登陸的代碼來(lái)講解自定義異常:

class LogIn {
    private String name ="Admin";//用戶(hù)名
    private String password= "CsDn1263987..0";
    public void logInFor(String name,String password) throws UserNameErrorExecption, PasswordErrorException {
        if(!this.name.equals(name)){
            throw new UserNameErrorExecption("用戶(hù)名參數(shù)異常?。。?quot;);
        }
        if(!this.password.equals(password)) {
            throw  new PasswordErrorException("用戶(hù)密碼參數(shù)異常?。?!");
        }
        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("用戶(hù)名錯(cuò)誤?。?!");
        }catch(PasswordErrorException passwordError) {
            passwordError.printStackTrace();
            System.out.println("密碼錯(cuò)誤?。?!");
        }
    }
}

自定義異常:

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

這就是我們定義的兩個(gè)異常。

通過(guò)繼承Exception來(lái)定義兩個(gè)異常。

一般我們自定義異常要繼承Exception或者是RunTimeException,定義其他的也可以。

  • 自定義異常通常會(huì)繼承自 Exception 或者 RuntimeException

  • 繼承自 Exception 的異常默認(rèn)是受查異常

  • 繼承自 RuntimeException 的異常默認(rèn)是非受查異常

關(guān)于“Java異常的處理方式有哪些”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí),可以關(guān)注億速云行業(yè)資訊頻道,小編每天都會(huì)為大家更新不同的知識(shí)點(diǎn)。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI