Java中異常的產(chǎn)生原因及如何處理

本篇內(nèi)容主要講解“Java中異常的產(chǎn)生原因及如何處理”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“Java中異常的產(chǎn)生原因及如何處理”吧!

創(chuàng)新互聯(lián)建站是專業(yè)的深圳網(wǎng)站建設(shè)公司,深圳接單;提供成都做網(wǎng)站、網(wǎng)站制作、成都外貿(mào)網(wǎng)站建設(shè),網(wǎng)頁設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行深圳網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來合作!

Java中異常的產(chǎn)生原因及如何處理

Java中的異常(Exception)又稱為例外,是一個(gè)在程序執(zhí)行期間發(fā)生的事件,它中斷正在執(zhí)行程序的正常指令流。為了能夠及時(shí)有效地處理程序中的運(yùn)行錯(cuò)誤,必須使用異常類。

1. 異常產(chǎn)生的原因和分類

1.1 異常產(chǎn)生的原因

在Java中異常產(chǎn)生,主要是有三種原因:

(1)編寫程序代碼中的錯(cuò)誤產(chǎn)生的異常,比如數(shù)組越界、空指針異常等,這種異常叫做未檢查的異常,一般需要在類中處理這些異常

(2)Java內(nèi)部錯(cuò)誤發(fā)生的異常,Java虛擬機(jī)產(chǎn)生異常

(3)通過throw(拋出異常)語句手動(dòng)生成的異常,這種異常叫做檢查的異常,一般是用來給方法調(diào)用者一些必要的信息

1.2 異常分類

Java中異常的產(chǎn)生原因及如何處理

(1)Throwable:是異常體系的頂層類,其派生出兩個(gè)重要的子類, Error 和 Exception

         而 Error 和 Exception 兩子類分別表示錯(cuò)誤和異常。

         區(qū)別就是不檢查異常(Unchecked Exception)和檢查異常(Checked Exception)。

(2)Exception 類用于用戶程序可能出現(xiàn)的異常情況,它也是用來創(chuàng)建自定義異常類型類的類。

(3)Error 定義了在通常環(huán)境下不希望被程序捕獲的異常。Error 類型的異常用于 Java 運(yùn)行時(shí)由系統(tǒng)顯示與運(yùn)行時(shí)系統(tǒng)本身有關(guān)的錯(cuò)誤。堆棧溢出是這種錯(cuò)誤的一例。

異??赡茉诰幾g時(shí)發(fā)生,也有可能在程序運(yùn)行時(shí)發(fā)生,根據(jù)發(fā)生時(shí)機(jī)不同,可以分為:

運(yùn)行時(shí)異常都是 RuntimeException 類及其子類異常,如 NullPointerException、IndexOutOfBoundsException 等,這些異常是不檢查異常,程序中可以選擇捕獲處理,也可以不處理。這些異常一般由程序邏輯錯(cuò)誤引起,程序應(yīng)該從邏輯角度盡可能避免這類異常的發(fā)生。

比如:

Java中異常的產(chǎn)生原因及如何處理

編譯時(shí)異常是指 RuntimeException 以外的異常,類型上都屬于 Exception 類及其子類。從程序語法角度講是必須進(jìn)行處理的異常,如果不處理,程序就不能編譯通過。如 IOException、ClassNotFoundException 等以及用戶自定義的 Exception 異常,一般情況下不自定義檢查異常。

比如

class Person implements Cloneable{
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class Test01 {

    public static void main(String[] args) {
        Person person =new Person();
        Person person1 =(Person) person.clone();
    }
}

Java中異常的產(chǎn)生原因及如何處理

2. 異常的處理

2.1 防御式編程

錯(cuò)誤在代碼中是客觀存在的. 所以要讓程序出現(xiàn)問題的時(shí)候快速通知程序猿.

通知有兩種方式:

(1)LBYL 在操作之前就做充分的檢查

private static int pide() {
        int a = 0, b = 0;
        Scanner scanner = new Scanner(System.in);
        a = scanner.nextInt();
        b = scanner.nextInt();
        if (b == 0) {
            System.out.println("除數(shù)為0");
            return 0;
        } else {
            return a / b;
        }
    }

缺點(diǎn):正常流程和錯(cuò)誤處理流程代碼混在一起, 代碼整體條理不清晰。

(2)EAFP 先操作遇到問題再處理

private static int pide() {
        int a = 0, b = 0;
        try (Scanner scanner = new Scanner(System.in)) {
            a = scanner.nextInt();
            b = scanner.nextInt();
            return a / b;
        } catch (ArithmeticException exception) {
            System.out.println("除數(shù)為0");
            return 0;
        } 
    }

優(yōu)點(diǎn):正常流程和錯(cuò)誤流程是分離開的, 程序員更關(guān)注正常流程,代碼更清晰,容易理解代碼

處理異常的核心思想就是EAFP

2.2 異常的拋出(throw)

在編寫程序時(shí),如果程序中出現(xiàn)錯(cuò)誤,這就需要將錯(cuò)誤的信息通知給調(diào)用者

這里就可以借助關(guān)鍵字throw,拋出一個(gè)指定的異常對象,將錯(cuò)誤信息告知給調(diào)用者。

比如寫一個(gè)運(yùn)行時(shí)異常

    public static void func2(int a) {
        if(a == 0) {
           //拋出的是一個(gè)指定的異常,最多的使用方式是,拋出一個(gè)自定義的異常
            throw new RuntimeException("a==0");
        }
    }
    public static void main(String[] args) {
        func2(0);
    }

Java中異常的產(chǎn)生原因及如何處理 注意:

(1)throw必須寫在方法體內(nèi)部

(2)如果拋出的是編譯時(shí)異常,用戶就必須要處理,否則無法通過編譯

Java中異常的產(chǎn)生原因及如何處理

(3)如果拋出的運(yùn)行時(shí)異常,則可以不用處理,直接交給JVM來處理

(4)一旦出現(xiàn)異常,后面的代碼就不會(huì)執(zhí)行

Java中異常的產(chǎn)生原因及如何處理

2.3 異常的捕獲

2.3.1 throws異常聲明

Java中異常的產(chǎn)生原因及如何處理

 throws處在方法聲明時(shí)參數(shù)列表之后,當(dāng)方法中拋出編譯時(shí)異常,用戶不想處理該異常,

此時(shí)就可以借助throws將異常拋 給方法的調(diào)用者來處理。

格式:  

修飾符 返回值類型 方法名(參數(shù)列表) throws 異常類型 {  

}  

如果說方法內(nèi)部拋出了多個(gè)異常,throws之后就必須跟多個(gè)異常類型,用逗號(hào)進(jìn)行分隔

    public static void func2(int a) throws CloneNotSupportedException, FileNotFoundException {
        if(a == 0) {
            throw new CloneNotSupportedException("a==0");
        }
        if(a == 1) {
            throw new FileNotFoundException();
        }
    }

  如果拋出多個(gè)異常類型有父子關(guān)系,直接聲明父類

    public static void func2(int a) throws Exception {
        if(a == 0) {
            throw new CloneNotSupportedException("a==0");
        }
        if(a == 1) {
            throw new FileNotFoundException();
        }
    }

調(diào)用聲明拋出異常的方法時(shí),調(diào)用者必須對該異常進(jìn)行處理,或者繼續(xù)使用throws拋出

   public static void main(String[] args) throws FileNotFoundException, CloneNotSupportedException {
        func2(0);
    }

2.3.2 try-catch捕獲異常并處理

當(dāng)程序拋出異常的時(shí)候,程序員通過try-each處理了異常

    public static void main(String[] args) {
        try {
            int[] array = null;
            System.out.println(array.length);
        }catch (NullPointerException e) {
            System.out.println("捕獲到了一個(gè)空指針異常!");
        }
        System.out.println("其他程序!");
    }

如果程序拋出異常,不處理異常,那就會(huì)交給JVM處理,JVM處理就會(huì)把程序立即終止

并且,即使用了try-each 也必須捕獲一個(gè)對應(yīng)的異常,如果不是對應(yīng)異常,也會(huì)讓JVM進(jìn)行處理

Java中異常的產(chǎn)生原因及如何處理

 如果try拋出多個(gè)異常,就必須用多個(gè)catch進(jìn)行捕獲

這里注意,用多個(gè)catch進(jìn)行捕獲,不是同時(shí)進(jìn)行捕獲的,因?yàn)椴豢赡芡瑫r(shí)拋不同的異常

    public static void main(String[] args) {
        try {
            int[] array = null;
            System.out.println(array.length);
        }catch (NullPointerException e) {
            System.out.println("捕獲到了一個(gè)空指針異常!");
        }catch (ArithmeticException e) {
            System.out.println("捕獲到了一個(gè)算術(shù)異常!");
        }
        System.out.println("其它代碼邏輯!");
    }

也可以簡寫一下

    public static void main(String[] args) {
        try {
            int[] array = null;
            System.out.println(array.length);
        }catch (NullPointerException  | ArithmeticException e) {
            System.out.println("捕獲到了一個(gè)空指針或算術(shù)異常!");
        }
        System.out.println("其它代碼邏輯!");
    }

如果異常之間具有父子關(guān)系,那就必須子類異常在前,父類異常在后catch,不然會(huì)報(bào)錯(cuò)  

    public static void main(String[] args) {
        try {
            int[] array = null;
            System.out.println(array.length);
        }catch (NullPointerException e) {
            System.out.println("捕獲到了一個(gè)空指針異常!");
        }catch (Exception) {
            System.out.println("捕獲到了一個(gè)算術(shù)異常!");
        }
        System.out.println("其它代碼邏輯!");
    }

2.3.3 finally

finally用來進(jìn)行資源回收,不論程序正常運(yùn)行還是退出,都需要回收資源

并且異常會(huì)引發(fā)程序的跳轉(zhuǎn),可能會(huì)導(dǎo)致有些語句執(zhí)行不到

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        try {
            int[] array = null;
            System.out.println(array.length);
        }catch (NullPointerException e) {
            System.out.println("捕獲到了一個(gè)空指針異常!");
        }catch (ArithmeticException e) {
            System.out.println("捕獲到了一個(gè)算術(shù)異常!");
        }finally {
            scanner.close();
            System.out.println("進(jìn)行資源關(guān)閉!");
        }
        System.out.println("其它代碼邏輯!");
    }

Java中異常的產(chǎn)生原因及如何處理

如果不為空,那么finally還會(huì)被執(zhí)行嗎

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        try {
            int[] array = {1,2,3};
            System.out.println(array.length);
        }catch (NullPointerException e) {
            System.out.println("捕獲到了一個(gè)空指針異常!");
        }catch (ArithmeticException e) {
            System.out.println("捕獲到了一個(gè)算術(shù)異常!");
        }finally {
            scanner.close();
            System.out.println("進(jìn)行資源關(guān)閉!");
        }
        System.out.println("其它代碼邏輯!");
    }

Java中異常的產(chǎn)生原因及如何處理

所以,不管程序會(huì)不會(huì)拋出異常,finally都會(huì)執(zhí)行

如果將資源寫在try中會(huì)自動(dòng)幫助,關(guān)掉資源的

    public static void main(String[] args) {
        try (Scanner scanner = new Scanner(System.in)) {
            int[] array = {1, 2, 3};
            System.out.println(array.length);
        } catch (NullPointerException e) {
            System.out.println("捕獲到了一個(gè)空指針異常!");
        } catch (ArithmeticException e) {
            System.out.println("捕獲到了一個(gè)算術(shù)異常!");
        } finally {
            System.out.println("進(jìn)行資源關(guān)閉!");
        }
        System.out.println("其它代碼邏輯!");
    }

下面看這一段代碼

    public static int func(int a) {
        try{
            if(a == 0) {
                throw  new ArithmeticException();
            }
            return a;
        } catch (ArithmeticException e) {
            System.out.println("算術(shù)異常!");
        } finally {
            return 20;
        }
    }

    public static void main(String[] args) {
        System.out.println(func(10));
    }

Java中異常的產(chǎn)生原因及如何處理

可以發(fā)現(xiàn)即使有return,finally也會(huì)被執(zhí)行

總結(jié)一下:

throw拋出異常,throws聲明異常

finally語句一定會(huì)執(zhí)行

3.自定義異常類

雖然java中有很多異常類,但是在實(shí)際開發(fā)中所遇到的一些異常,不能完全表示,

所以這就需要我們自定義異常類

舉一個(gè)例子

先自定義一個(gè)運(yùn)行時(shí)異常

//自定義了一個(gè)運(yùn)行時(shí)異常
public class MyException extends RuntimeException{
    public MyException() {

    }
    public MyException(String message) {
        super(message);
    }
}

寫一個(gè)類來捕獲這個(gè)自定義異常

public class Test04 {
    public static void func(int a ) {
        throw new MyException("呵呵!");
    }

    public static void main(String[] args) {
        try {
            func(20);
        }catch (MyException myException) {
            myException.printStackTrace();
        }finally {
            System.out.println("sadasdasd");
        }

    }
}

下面寫一個(gè)用戶登錄的自定義異常類

class UserNameException extends RuntimeException {
    public UserNameException() {

    }
    public UserNameException(String message) {
        super(message);
    }
}
class PasswordException extends RuntimeException {

    public PasswordException() {
    }

    public PasswordException(String message) {
        super(message);
    }
}
public class LogIn {
    private static String uName = "admin";
    private static String pword = "1111";

    public static void loginInfo(String userName, String password) {
        if ( !uName.equals(userName)) {
            throw new UserNameException("用戶名錯(cuò)誤!");
        }
        if ( !pword.equals(password)) {
            throw new RuntimeException("密碼錯(cuò)誤!");

        }
        System.out.println("登錄成功!");
    }

    public static void main(String[] args) {
        try {
            loginInfo("admin","1111");
        } catch (UserNameException e) {
            e.printStackTrace();
        } catch (PasswordException e) {
            e.printStackTrace();
        }
    }
}

注意:

自定義異常默認(rèn)會(huì)繼承 Exception 或者 RuntimeException 

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

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

到此,相信大家對“Java中異常的產(chǎn)生原因及如何處理”有了更深的了解,不妨來實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

新聞名稱:Java中異常的產(chǎn)生原因及如何處理
文章路徑:http://muchs.cn/article22/iiocjc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供關(guān)鍵詞優(yōu)化、品牌網(wǎng)站設(shè)計(jì)、Google、面包屑導(dǎo)航、App開發(fā)、App設(shè)計(jì)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)頁設(shè)計(jì)公司