鍍金池/ 教程/ Java/ 異常(一)
Java 集合細節(jié)(四):保持 compareTo 和 equals 同步
Iterator
使用序列化實現(xiàn)對象的拷貝
fail-fast 機制
關(guān)鍵字 final
Vector
HashTable
Java 集合細節(jié)(一):請為集合指定初始容量
強制類型轉(zhuǎn)換
數(shù)組之一:認識 JAVA 數(shù)組
Java 集合細節(jié)(三):subList 的缺陷
hashCode
ArrayList
數(shù)組之二
List 總結(jié)
LinkedList
Java 提高篇(九)—–實現(xiàn)多重繼承
Java 的四舍五入
關(guān)鍵字 static
理解 Java 的三大特性之多態(tài)
抽象類與接口
集合大家族
異常(二)
Java 集合細節(jié)(二):asList 的缺陷
Map 總結(jié)
TreeSet
equals() 方法總結(jié)
Java 提高篇(十)—–詳解匿名內(nèi)部類
HashMap
Stack
詳解內(nèi)部類
TreeMap
異常(一)
詳解 Java 定時任務(wù)
HashSet
字符串
理解 Java 的三大特性之繼承
理解 Java 的三大特性之封裝
代碼塊

異常(一)

Java 的基本理念是“結(jié)構(gòu)不佳的代碼不能運行”!!?。。?/code>

大成若缺,其用不弊。

大盈若沖,其用不窮。

在這個世界不可能存在完美的東西,不管完美的思維有多么縝密,細心,我們都不可能考慮所有的因素,這就是所謂的智者千慮必有一失。同樣的道理,計算機的世界也是不完美的,異常情況隨時都會發(fā)生,我們所需要做的就是避免那些能夠避免的異常,處理那些不能避免的異常。這里我將記錄如何利用異常還程序一個“完美世界”。

一、為什么要使用異常

首先我們可以明確一點就是異常的處理機制可以確保我們程序的健壯性,提高系統(tǒng)可用率。雖然我們不是特別喜歡看到它,但是我們不能不承認它的地位,作用。有異常就說明程序存在問題,有助于我們及時改正。在我們的程序設(shè)計當做,任何時候任何地方因為任何原因都有可能會出現(xiàn)異常,在沒有異常機制的時候我們是這樣處理的:通過函數(shù)的返回值來判斷是否發(fā)生了異常(這個返回值通常是已經(jīng)約定好了的),調(diào)用該函數(shù)的程序負責檢查并且分析返回值。雖然可以解決異常問題,但是這樣做存在幾個缺陷:

1、容易混淆。如果約定返回值為 -11111 時表示出現(xiàn)異常,那么當程序最后的計算結(jié)果真的為 -1111 呢?

2、代碼可讀性差。將異常處理代碼和程序代碼混淆在一起將會降低代碼的可讀性。

3、由調(diào)用函數(shù)來分析異常,這要求程序員對庫函數(shù)有很深的了解。

在 OO 中提供的異常處理機制是提供代碼健壯的強有力的方式。

使用異常機制它能夠降低錯誤處理代碼的復雜度,如果不使用異常,那么就必須檢查特定的錯誤,并在程序中的許多地方去處理它,而如果使用異常,那就不必在方法調(diào)用處進行檢查,因為異常機制將保證能夠捕獲這個錯誤,并且,只需在一個地方處理錯誤,即所謂的異常處理程序中。這種方式不僅節(jié)約代碼,而且把“概述在正常執(zhí)行過程中做什么事”的代碼和“出了問題怎么辦”的代碼相分離??傊?,與以前的錯誤處理方法相比,異常機制使代碼的閱讀、編寫和調(diào)試工作更加井井有條。(摘自《Think in Java》)。

在初學時,總是聽老師說把有可能出錯的地方記得加異常處理,剛剛開始還不明白,有時候還覺得只是多此一舉,現(xiàn)在隨著自己的不斷深入,代碼編寫多了,漸漸明白了異常是非常重要的。

二、基本定義

在《Think in Java》中是這樣定義異常的:異常情形是指阻止當前方法或者作用域繼續(xù)執(zhí)行的問題。在這里一定要明確一點:異常代碼某種程度的錯誤,盡管 Java 有異常處理機制,但是我們不能以“正常”的眼光來看待異常,異常處理機制的原因就是告訴你:這里可能會或者已經(jīng)產(chǎn)生了錯誤,您的程序出現(xiàn)了不正常的情況,可能會導致程序失敗!

那么什么時候才會出現(xiàn)異常呢?只有在你當前的環(huán)境下程序無法正常運行下去,也就是說程序已經(jīng)無法來正確解決問題了,這時它所就會從當前環(huán)境中跳出,并拋出異常。拋出異常后,它首先會做幾件事。首先,它會使用 new 創(chuàng)建一個異常對象,然后在產(chǎn)生異常的位置終止程序,并且從當前環(huán)境中彈出對異常對象的引用,這時。異常處理機制就會接管程序,并開始尋找一個恰當?shù)牡胤絹砝^續(xù)執(zhí)行程序,這個恰當?shù)牡胤骄褪钱惓L幚沓绦?,它的任?wù)就是將程序從錯誤狀態(tài)恢復,以使程序要么換一種方法執(zhí)行,要么繼續(xù)執(zhí)行下去。

總的來說異常處理機制就是當程序發(fā)生異常時,它強制終止程序運行,記錄異常信息并將這些信息反饋給我們,由我們來確定是否處理異常。

二、基本定義

在《Think in Java》中是這樣定義異常的:異常情形是指阻止當前方法或者作用域繼續(xù)執(zhí)行的問題。在這里一定要明確一點:異常代碼某種程度的錯誤,盡管 Java 有異常處理機制,但是我們不能以“正?!钡难酃鈦砜创惓?,異常處理機制的原因就是告訴你:這里可能會或者已經(jīng)產(chǎn)生了錯誤,您的程序出現(xiàn)了不正常的情況,可能會導致程序失?。?/p>

那么什么時候才會出現(xiàn)異常呢?只有在你當前的環(huán)境下程序無法正常運行下去,也就是說程序已經(jīng)無法來正確解決問題了,這時它所就會從當前環(huán)境中跳出,并拋出異常。拋出異常后,它首先會做幾件事。首先,它會使用 new 創(chuàng)建一個異常對象,然后在產(chǎn)生異常的位置終止程序,并且從當前環(huán)境中彈出對異常對象的引用,這時。異常處理機制就會接管程序,并開始尋找一個恰當?shù)牡胤絹砝^續(xù)執(zhí)行程序,這個恰當?shù)牡胤骄褪钱惓L幚沓绦颍娜蝿?wù)就是將程序從錯誤狀態(tài)恢復,以使程序要么換一種方法執(zhí)行,要么繼續(xù)執(zhí)行下去。

總的來說異常處理機制就是當程序發(fā)生異常時,它強制終止程序運行,記錄異常信息并將這些信息反饋給我們,由我們來確定是否處理異常。

三、異常體系

Java 為我們提供了非常完美的異常處理機制,使得我們可以更加專心于我們的程序,在使用異常之前我們需要了解它的體系結(jié)構(gòu):如下(該圖摘自:http://blog.csdn.net/zhangerqing/article/details/8248186)。

從上面這幅圖可以看出,Throwable 是 java 語言中所有錯誤和異常的超類(萬物即可拋)。它有兩個子類:Error、Exception。

其中 Error 為錯誤,是程序無法處理的,如 OutOfMemoryError、ThreadDeath 等,出現(xiàn)這種情況你唯一能做的就是聽之任之,交由 JVM 來處理,不過 JVM 在大多數(shù)情況下會選擇終止線程。

而 Exception 是程序可以處理的異常。它又分為兩種 CheckedException(受撿異常),一種是 UncheckedException(不受檢異常)。其中 CheckException 發(fā)生在編譯階段,必須要使用 try…catch(或者throws)否則編譯不通過。而 UncheckedException 發(fā)生在運行期,具有不確定性,主要是由于程序的邏輯問題所引起的,難以排查,我們一般都需要縱觀全局才能夠發(fā)現(xiàn)這類的異常錯誤,所以在程序設(shè)計中我們需要認真考慮,好好寫代碼,盡量處理異常,即使產(chǎn)生了異常,也能盡量保證程序朝著有利方向發(fā)展。

所以:對于可恢復的條件使用被檢查的異常(CheckedException),對于程序錯誤(言外之意不可恢復,大錯已經(jīng)釀成)使用運行時異常(RuntimeException)。

Java 的異常類實在是太多了,產(chǎn)生的原因也千變?nèi)f化,所以下篇博文我將會整理,統(tǒng)計 Java 中經(jīng)常出現(xiàn)的異常,望各位關(guān)注?。?/strong>

四、異常使用

在網(wǎng)上看了這樣一個搞笑的話:世界上最真情的相依,是你在 try 我在 catch。無論你發(fā)神馬脾氣,我都默默承受,靜靜處理。對于初學者來說異常就是 try…catch,(鄙人剛剛接觸時也是這么認為的,碰到異常就是 try…catch)。個人感覺 try…catch 確實是用的最多也是最實用的。

在異常中 try 快包含著可能出現(xiàn)異常的代碼塊,catch 塊捕獲異常后對異常進行處理。先看如下實例:


    public class ExceptionTest {
        public static void main(String[] args) {
            String file = "D:\\exceptionTest.txt";
            FileReader reader;
            try {
                reader = new FileReader(file);
                Scanner in = new Scanner(reader);  
                String string = in.next();  
                System.out.println(string + "不知道我有幸能夠執(zhí)行到不.....");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
                System.out.println("對不起,你執(zhí)行不到...");
            }  
            finally{
                System.out.println("finally 在執(zhí)行...");
            }
        }
    }

這是段非常簡單的程序,用于讀取 D 盤目錄下的 exceptionText.txt 文件,同時讀取其中的內(nèi)容、輸出。首先 D 盤沒有該文件,運行程序結(jié)果如下:


    java.io.FileNotFoundException: D:\exceptionTest.txt  (系統(tǒng)找不到指定的文件。)
        at java.io.FileInputStream.open(Native Method)
        at java.io.FileInputStream.<init>(FileInputStream.java:106)
        at java.io.FileInputStream.<init>(FileInputStream.java:66)
        at java.io.FileReader.<init>(FileReader.java:41)
        at com.test9.ExceptionTest.main(ExceptionTest.java:19)
    對不起,你執(zhí)行不到...
    finally 在執(zhí)行...

從這個結(jié)果我們可以看出這些:

1、當程序遇到異常時會終止程序的運行(即后面的代碼不在執(zhí)行),控制權(quán)交由異常處理機制處理。

2、catch 捕捉異常后,執(zhí)行里面的函數(shù)。

當我們在 D 盤目錄下新建一個 exceptionTest.txt 文件后,運行程序結(jié)果如下:


    1111不知道我有幸能夠執(zhí)行到不.....
    finally 在執(zhí)行...

11111 是該文件中的內(nèi)容。從這個運行結(jié)果可以得出這個結(jié)果:不論程序是否發(fā)生異常,finally 代碼塊總是會執(zhí)行。所以 finally 一般用來關(guān)閉資源。

在這里我們在看如下程序:


    public class ExceptionTest {
        public static void main(String[] args) {
            int[] a = {1,2,3,4};
            System.out.println(a[4]);
            System.out.println("我執(zhí)行了嗎???");
        }
    }

程序運行結(jié)果:


    Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4
        at com.test9.ExceptionTest.main(ExceptionTest.java:14)

各位請注意這個異常信息和上面的異常信息錯誤,為了看得更加清楚,我將 他們列在一起:


    java.io.FileNotFoundException: D:\exceptionTest.txt (系統(tǒng)找不到指定的文件。)
            Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4

在這里我們發(fā)現(xiàn)兩個異常之間存在如下區(qū)別:第二個異常信息多了Exception in thread “main”,這顯示了出現(xiàn)異常信息的位置。在這里可以得到如下結(jié)論:若程序中顯示的聲明了某個異常,則拋出異常時不會顯示出處,若程序中沒有顯示的聲明某個異常,當拋出異常時,系統(tǒng)會顯示異常的出處。

由于這篇博文會比較長,所以分兩篇來介紹。下篇博文主要介紹 Java 異常的自定義異常、異常鏈、異常的使用誤區(qū)、使用異常注意地方以及 try…catch、throw、throws。望各位看客關(guān)注?。。?!