亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

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

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

java異常處理方法是什么

發布時間:2021-11-24 15:03:45 來源:億速云 閱讀:134 作者:iii 欄目:云計算

這篇文章主要介紹“java異常處理方法是什么”,在日常操作中,相信很多人在java異常處理方法是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”java異常處理方法是什么”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

異常簡介

先上個圖,看一下常見的幾個異常類型。

java異常處理方法是什么

所有的異常都來自于Throwable。Throwable有兩個子類,Error和Exception。

Error通常表示的是嚴重錯誤,這些錯誤是不建議被catch的。

注意這里有一個例外,比如ThreadDeath也是繼承自Error,但是它表示的是線程的死亡,雖然不是嚴重的異常,但是因為應用程序通常不會對這種異常進行catch,所以也歸類到Error中。

Exception表示的是應用程序希望catch住的異常。

在Exception中有一個很特別的異常叫做RuntimeException。RuntimeException叫做運行時異常,是不需要被顯示catch住的,所以也叫做unchecked Exception。而其他非RuntimeException的Exception則需要顯示try catch,所以也叫做checked Exception。

不要忽略checked exceptions

我們知道checked exceptions是一定要被捕獲的異常,我們在捕獲異常之后通常有兩種處理方式。

第一種就是按照業務邏輯處理異常,第二種就是本身并不處理異常,但是將異常再次拋出,由上層代碼來處理。

如果捕獲了,但是不處理,那么就是忽略checked exceptions。

接下來我們來考慮一下java中線程的中斷異常。

java中有三個非常相似的方法interrupt,interrupted和isInterrupted。

isInterrupted()只會判斷是否被中斷,而不會清除中斷狀態。

interrupted()是一個類方法,調用isInterrupted(true)判斷的是當前線程是否被中斷。并且會清除中斷狀態。

前面兩個是判斷是否中斷的方法,而interrupt()就是真正觸發中斷的方法。

它的工作要點有下面4點:

  1. 如果當前線程實例在調用Object類的wait(),wait(long)或wait(long,int)方法或join(),join(long),join(long,int)方法,或者在該實例中調用了Thread.sleep(long)或Thread.sleep(long,int)方法,并且正在阻塞狀態中時,則其中斷狀態將被清除,并將收到InterruptedException。

  2. 如果此線程在InterruptibleChannel上的I / O操作中處于被阻塞狀態,則該channel將被關閉,該線程的中斷狀態將被設置為true,并且該線程將收到java.nio.channels.ClosedByInterruptException異常。

  3. 如果此線程在java.nio.channels.Selector中處于被被阻塞狀態,則將設置該線程的中斷狀態為true,并且它將立即從select操作中返回。

  4. 如果上面的情況都不成立,則設置中斷狀態為true。

看下面的例子:

public void wrongInterrupted(){
        try{
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

上面代碼中我們捕獲了一個InterruptedException,但是我們僅僅是打印出了異常信息,并沒有做任何操作。這樣程序的表現和沒有發送一異常一樣,很明顯是有問題的。

根據上面的介紹,我們知道,interrupted()方法會清除中斷狀態,所以,如果我們自身處理不了異常的情況下,需要重新調用Thread.currentThread().interrupt()重新拋出中斷,由上層代碼負責處理,如下所示。

public void correctInterrupted(){
        try{
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }

不要在異常中暴露敏感信息

遇到異常的時候,通常我們需要進行一定程度的日志輸出,從而來定位異常。但是我們在做日志輸出的時候,一定要注意不要暴露敏感信息。

下表可以看到異常信息可能會暴露的敏感信息:

java異常處理方法是什么

除了敏感信息之外,我們還要做好日志信息的安全保護。

在處理捕獲的異常時,需要恢復對象的初始狀態

如果我們在處理異常的時候,修改了對象中某些字段的狀態,在捕獲異常的時候需要怎么處理呢?

private int age=30;

    public void wrongRestore(){
        try{
            age=20;
            throw new IllegalStateException("custom exception!");
        }catch (IllegalStateException e){
            System.out.println("we do nothing");
        }
    }

上面的例子中,我們將age重置為20,然后拋出了異常。雖然拋出了異常,但是我們并沒有重置age,最后導致age最終被修改了。

整個restore的邏輯沒有處理完畢,但是我們部分修改了對象的數據,這是很危險的。

實際上,我們需要一個重置:

public void rightRestore(){
        try{
            age=20;
            throw new IllegalStateException("custom exception!");
        }catch (IllegalStateException e){
            System.out.println("we do nothing");
            age=30;
        }
    }

不要手動完成finally block

我們在使用try-finally和try-catch-finally語句時,一定不要在finally block中使用return, break, continue或者throw語句。

為什么呢?

根據Java Language Specification(JLS)的說明,finally block一定會被執行,不管try語句中是否拋出異常。

在try-finally和try-catch-finally語句中,如果try語句中拋出了異常R,然后finally block被執行,這時候有兩種情況:

  • 如果finally block正常執行,那么try語句被終止的原因是異常R。

  • 如果在finally block中拋出了異常S,那么try語句被終止的原因將會變成S。

我們舉個例子:

public class FinallyUsage {

    public boolean wrongFinally(){
        try{
            throw new IllegalStateException("my exception!");
        }finally {
            System.out.println("Code comes to here!");
            return true;
        }
    }

    public boolean rightFinally(){
        try{
            throw new IllegalStateException("my exception!");
        }finally {
            System.out.println("Code comes to here!");
        }
    }

    public static void main(String[] args) {
        FinallyUsage finallyUsage=new FinallyUsage();
        finallyUsage.wrongFinally();
        finallyUsage.rightFinally();
    }
}

上面的例子中,我們定義了兩個方法,一個方法中我們在finally中直接return,另一方法中,我們讓finally正常執行完畢。

最終,我們可以看到wrongFinally將異常隱藏了,而rightFinally保留了try的異常。

同樣的,如果我們在finally block中拋出了異常,我們一定要記得對其進行捕獲,否則將會隱藏try block中的異常信息。

不要捕獲NullPointerException和它的父類異常

通常來說NullPointerException表示程序代碼有邏輯錯誤,是需要程序員來進行代碼邏輯修改,從而進行修復的。

比如說加上一個null check。

不捕獲NullPointerException的原因有三個。

  1. 使用null check的開銷要遠遠小于異常捕獲的開銷。

  2. 如果在try block中有多個可能拋出NullPointerException的語句,我們很難定位到具體的錯誤語句。

  3. 最后,如果發生了NullPointerException,程序基本上不可能正常運行或者恢復,所以我們需要提前進行null check的判斷。

同樣的,程序也不要對NullPointerException的父類RuntimeException, Exception, or Throwable進行捕捉。

不要throw RuntimeException, Exception, or Throwable

我們拋出異常主要是為了能夠找到準確的處理異常的方法,如果直接拋出RuntimeException, Exception, 或者 Throwable就會導致程序無法準確處理特定的異常。

通常來說我們需要自定義RuntimeException, Exception, 或者 Throwable的子類,通過具體的子類來區分具體的異常類型。

不要拋出未聲明的checked Exception

一般來說checked Exception是需要顯示catch住,或者在調用方法上使用throws做申明的。

但是我們可以通過某些手段來繞過這種限制,從而在使用checked Exception的時候不需要遵守上述規則。

當然這樣做是需要避免的。我們看一個例子:

private static Throwable throwable;

    private ThrowException() throws Throwable {
        throw throwable;
    }

    public static synchronized void undeclaredThrow(Throwable throwable) {

        ThrowException.throwable = throwable;
        try {
                ThrowException.class.newInstance();
            } catch (InstantiationException e) {
            } catch (IllegalAccessException e) {
        } finally {
            ThrowException.throwable = null;
        }
    }

上面的例子中,我們定義了一個ThrowException的private構造函數,這個構造函數會throw一個throwable,這個throwable是從方法傳入的。

在undeclaredThrow方法中,我們調用了ThrowException.class.newInstance()實例化一個ThrowException實例,因為需要調用構造函數,所以會拋出傳入的throwable。

因為Exception是throwable的子類,如果我們在調用的時候傳入一個checked Exception,很明顯,我們的代碼并沒有對其進行捕獲:

public static void main(String[] args) {
        ThrowException.undeclaredThrow(
                new Exception("Any checked exception"));
    }

怎么解決這個問題呢?換個思路,我們可以使用Constructor.newInstance()來替代class.newInstance()。

try {
        Constructor constructor =
                    ThrowException.class.getConstructor(new Class<?>[0]);
            constructor.newInstance();
        } catch (InstantiationException e) {
        } catch (InvocationTargetException e) {
            System.out.println("catch exception!");
        } catch (NoSuchMethodException e) {
        } catch (IllegalAccessException e) {
        } finally {
            ThrowException.throwable = null;
        }

上面的例子,我們使用Constructor的newInstance方法來創建對象的實例。和class.newInstance不同的是,這個方法會拋出InvocationTargetException異常,并且把所有的異常都封裝進去。

所以,這次我們獲得了一個checked Exception。

到此,關于“java異常處理方法是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

田林县| 阿瓦提县| 涿州市| 南部县| 青河县| 会理县| 崇左市| 芷江| 聂拉木县| 肇州县| 霍林郭勒市| 德格县| 西丰县| 平湖市| 尼木县| 清水县| 广灵县| 靖江市| 吉水县| 乐业县| 遂平县| 南阳市| 康平县| 佳木斯市| 石楼县| 德清县| 新沂市| 平顺县| 曲麻莱县| 惠水县| 六安市| 广昌县| 合肥市| 文化| 雅安市| 齐齐哈尔市| 泊头市| 新泰市| 堆龙德庆县| 靖宇县| 望城县|