15. Java異常處理

來源:互聯網
上載者:User

標籤:3.1.1   array   orm   ber   記憶體溢出   for   sum   串連   強制轉換   

 

1. Java異常處理

異常是程式中的一些錯誤,但並不是所有的錯誤都是異常,並且錯誤有時候是可以避免的。

比如說,你的代碼少了一個分號,那麼運行出來結果是提示是錯誤 java.lang.Error;如果你用System.out.println(11/0),那麼你是因為你用0做了除數,會拋出 java.lang.ArithmeticException 的異常。

異常發生的原因有很多,通常包含以下幾大類:

使用者輸入了非法資料。要開啟的檔案不存在。網路通訊時串連中斷,或者JVM記憶體溢出

這些異常有的是因為使用者錯誤引起,有的是程式錯誤引起的,還有其它一些是因為物理錯誤引起的。-

要理解Java異常處理是如何工作的,你需要掌握以下三種類型的異常:

檢查性異常:最具代表的檢查性異常是使用者錯誤或問題引起的異常,這是程式員無法預見的。例如要開啟一個不存在檔案時,一個異常就發生了,這些異常在編譯時間不能被簡單地忽略。運行時異常: 運行時異常是可能被程式員避免的異常。與檢查性異常相反,運行時異常可以在編譯時間被忽略。錯誤: 錯誤不是異常,而是脫離程式員控制的問題。錯誤在代碼中通常被忽略。例如,當棧溢出時,一個錯誤就發生了,它們在編譯也檢查不到的。

名詞解釋:

1.檢查性異常: 不處理編譯不能通過2.非檢查性異常:不處理編譯可以通過,如果有拋出直接拋到控制台3.運行時異常: 就是非檢查性異常4.非運行時異常: 就是檢查性異常

問題:我們曾經遇到過哪些異常?

2. Exception類的層次

所有的異常類是從 java.lang.Exception 類繼承的子類。

Exception 類是 Throwable 類的子類。除了Exception類外,Throwable還有一個子類Error 。

Java 程式通常不捕獲錯誤。錯誤一般發生在嚴重故障時,它們在Java程式處理的範疇之外。

Error 用來指示運行時環境發生的錯誤。

例如,JVM 記憶體溢出。一般地,程式不會從錯誤中恢複。

異常類有兩個主要的子類:IOException 類和 RuntimeException 類。

Java內建異常類:

非檢查性異常:

ArithmeticException 當出現異常的運算條件時,拋出此異常。例如,一個整數"除以零"時,拋出此類的一個執行個體。ArrayIndexOutOfBoundsException  用非法索引訪問數組時拋出的異常。如果索引為負或大於等於數組大小,則該索引為非法索引。ArrayStoreException 試圖將錯誤類型的Object Storage Service到一個對象數組時拋出的異常。ClassCastException  當試圖將對象強制轉換為不是執行個體的子類時,拋出該異常。IllegalArgumentException    拋出的異常表明向方法傳遞了一個不合法或不正確的參數。IllegalMonitorStateException    拋出的異常表明某一線程已經試圖等待對象的監視器,或者試圖通知其他正在等待對象的監視器而本身沒有指定監視器的線程。IllegalStateException   在非法或不適當的時間調用方法時產生的訊號。換句話說,即 Java 環境或 Java 應用程式沒有處於請求操作所要求的適當狀態下。IllegalThreadStateException 線程沒有處於請求操作所要求的適當狀態時拋出的異常。IndexOutOfBoundsException   指示某排序索引(例如對數組、字串或向量的排序)超出範圍時拋出。NegativeArraySizeException  如果應用程式試圖建立大小為負的數組,則拋出該異常。NullPointerException    當應用程式試圖在需要對象的地方使用 null 時,拋出該異常NumberFormatException   當應用程式試圖將字串轉換成一種數實值型別,但該字串不能轉換為適當格式時,拋出該異常。SecurityException   由安全管理器拋出的異常,指示存在安全侵犯。StringIndexOutOfBoundsException 此異常由 String 方法拋出,指示索引或者為負,或者超出字串的大小。UnsupportedOperationException   當不支援要求的操作時,拋出該異常。

檢查性異常類:

ClassNotFoundException  應用程式試圖載入類時,找不到相應的類,拋出該異常。CloneNotSupportedException  當調用 Object 類中的 clone 方法複製對象,但該對象的類無法實現 Cloneable 介面時,拋出該異常。IllegalAccessException  拒絕訪問一個類的時候,拋出該異常。InstantiationException  當試圖使用 Class 類中的 newInstance 方法建立一個類的執行個體,而指定的類對象因為是一個介面或是一個抽象類別而無法執行個體化時,拋出該異常。InterruptedException    一個線程被另一個線程中斷,拋出該異常。NoSuchFieldException    請求的變數不存在NoSuchMethodException   請求的方法不存在

異常的方法:

Throwable 類的主要方法:

1   public String getMessage()返回關於發生的異常的詳細資料。這個訊息在Throwable 類的建構函式中初始化了。2   public Throwable getCause()返回一個Throwable 對象代表異常原因。3   public String toString()使用getMessage()的結果返回類的串級名字。4   public void printStackTrace()列印toString()結果和棧層次到System.err,即錯誤輸出資料流。5   public StackTraceElement [] getStackTrace()返回一個包含堆棧層次的數組。下標為0的元素代表棧頂,最後一個元素代表方法呼叫堆疊的棧底。6   public Throwable fillInStackTrace()用當前的調用棧層次填充Throwable 對象棧層次,添加到棧層次任何先前資訊中。
3. 異常捕捉3.1 Try-catch捕捉3.1.1 Try-catch單重捕捉

使用 try 和 catch 關鍵字可以捕獲異常。try/catch 代碼塊放在異常可能發生的地方。

try/catch代碼塊中的代碼稱為保護代碼,使用 try/catch 的文法如下:

try{   // 程式碼}catch(ExceptionName e1){   //Catch 塊}

Catch 語句包含要捕獲異常類型的聲明。當保護代碼塊中發生一個異常時,try 後面的 catch 塊就會被檢查。

如果發生的異常包含在 catch 塊中,異常會被傳遞到該 catch 塊,這和傳遞一個參數到方法是一樣。

執行個體:

下面的例子中聲明有兩個元素的一個數組,當代碼試圖訪問數組的第三個元素的時候就會拋出一個異常。

// 檔案名稱 : ExcepTest.javaimport java.io.*;public class ExcepTest{   public static void main(String args[]){      try{         int a[] = new int[2];         System.out.println("Access element three :" + a[3]);      }catch(ArrayIndexOutOfBoundsException e){         System.out.println("Exception thrown  :" + e);      }      System.out.println("Out of the block");   }}

運行結果:

Exception thrown  :java.lang.ArrayIndexOutOfBoundsException: 3Out of the block
3.1.2 Try-catch多重捕獲

一個 try 代碼塊後面跟隨多個 catch 代碼塊的情況就叫多重捕獲。

多重捕獲塊的文法如下所示:

try{   // 程式碼}catch(異常類型1 異常的變數名1){  // 程式碼}catch(異常類型2 異常的變數名2){  // 程式碼}catch(異常類型2 異常的變數名2){  // 程式碼}

上面的程式碼片段包含了 3 個 catch塊。

可以在 try 語句後面添加任意數量的 catch 塊。

如果保護代碼中發生異常,異常被拋給第一個 catch 塊。

如果拋出異常的資料類型與 ExceptionType1 匹配,它在這裡就會被捕獲。

如果不匹配,它會被傳遞給第二個 catch 塊。

如此,直到異常被捕獲或者通過所有的 catch 塊。

try{  file = new FileInputStream(fileName);  x = (byte) file.read();}catch(IOException i){  i.printStackTrace();  return -1;}catch(FileNotFoundException f) //Not valid!{  f.printStackTrace();  return -1;}

我們通常在catch語句做如下處理:

   try{      可能出現異常的代碼   }catch(異常類型 e){      處理異常:       1 列印到控制台       2 儲存到檔案       3 還可能向外拋出新的異常   }finally{      }
3.2 throws/throw拋出異常

如果一個方法沒有捕獲一個檢查性異常,那麼該方法必須使用 throws 關鍵字來聲明。throws 關鍵字放在方法簽名的尾部。

也可以使用 throw 關鍵字拋出一個異常,無論它是新執行個體化的還是剛捕獲到的。

下面方法的聲明拋出一個 RemoteException 異常:

import java.io.*;public class className{  public void deposit(double amount) throws RemoteException  {    // Method implementation    throw new RemoteException();  }  //Remainder of class definition}

一個方法可以聲明拋出多個異常,多個異常之間用逗號隔開。

例如,下面的方法聲明拋出 RemoteException 和 InsufficientFundsException:

import java.io.*;public class className{   public void withdraw(double amount) throws RemoteException,                              InsufficientFundsException   {       // Method implementation   }   //Remainder of class definition}

throw和throws的區別:

throws使用在函數上throw使用在函數內throws後面跟的是異常類,可以跟多個,逗號隔開throw後面跟的是異常對象
3.3 finally異常的處理

finally 關鍵字用來建立在 try 代碼塊後面執行的代碼塊。

無論是否發生異常,finally 代碼塊中的代碼總會被執行。

在 finally 代碼塊中,可以運行清理類型等收尾善後性質的語句。

finally 代碼塊出現在 catch 代碼塊最後,文法如下:

try{  // 程式碼}catch(異常類型1 異常的變數名1){  // 程式碼}catch(異常類型2 異常的變數名2){  // 程式碼}finally{  // 程式碼}

執行個體:

public static void copy(File src,File des) {    BufferedReader br = null;    BufferedWriter bw = null;    try {        br = new BufferedReader(new FileReader(src));        bw = new BufferedWriter(new FileWriter(des));        char[] data = new char[4096];        int ch = 0;        while ((ch = br.read(data)) != -1) {            bw.write(data, 0, ch);        }    } catch (IOException e) {        e.printStackTrace();    }finally {        try {            if (br != null) {                br.close();            }            if (bw != null) {                bw.close();            }        } catch (IOException e) {            e.printStackTrace();        }    }}

這樣不論FileReader和FileWriter是否執行個體化成功,檔案是否存在,最後我們都可以關閉這兩個流

我們通常在finally代碼塊做如下處理:

1.關閉流資源(IO流部分講解)或者 釋放鎖--線程(以後課程學習)    簡單說明一下: 這裡的流,類似於水流的意思,比如一個水龍頭開啟,流出水,突然發生地震了(產生異常),沒有關閉水龍頭,那水就一直流著,然後可能導致短路,電路中斷,然後就可能引起火災;所以希望中途不管發生什麼異常情況,最終都應該關閉水龍頭。這樣就可以把關閉的代碼寫在finally裡面;2.釋放鎖 比如上廁所需要上鎖,然後完事了之後,最後在開鎖出來。    特點:如果在finally前面沒有執行系統退出(system.exit(0))的語句,此處的代碼始終都會執行。3.不建議此處放return語句來返回一個資料(讓程式難以理解,並且這裡也不應該放return)對於上面的結構,也有變種,比如:try{}finally{}只有try-finally,沒有catch,這種結構在講線程,釋放鎖學習

注意下面事項:

catch 不能獨立於 try 存在。在 try/catch 後面添加 finally 塊並非強制性要求的。try 代碼後不能既沒 catch 塊也沒 finally 塊。try, catch, finally 塊之間不能添加任何代碼。
4. 聲明自訂異常

在Java異常體系已經包含了很多異常類,但是還是不能滿足開發的日常情況那應該怎麼辦?

情境:

   1。假設使用者註冊過程中,發現使用者名稱重複了,把這種情況定義為異常類型;   2。設計一個使用者註冊的方法,方法裡面判斷使用者註冊的使用者名稱是否重複,如果重複,就產生一個異常對象;   3。調用註冊方法來註冊一個帳號,就會產生一個異常。產生異常之後,就選擇是拋出還是處理.

自訂異常的規則:

所有異常都必須是 Throwable 的子類。如果希望寫一個檢查性異常類,則需要繼承 Exception 類。如果你想寫一個運行時異常類,那麼需要繼承 RuntimeException 類。

1.定義一個異常類(使用者名稱重複異常)

package com.rimi.exception;public class NameRepeatException extends Exception {    public NameRepeatException(){        super();    }    public NameRepeatException(String msg){        super(msg);    }}

2.寫個測試類別

package com.rimi.lesson20;public class Test {    public static void main(String[] args) {        String[] names = { "張三", "李四", "王二", "麻子", };        try {            login("張三", names);        } catch (Exception e) {            // TODO: handle exception            System.out.println("異常拋出:" + e.getMessage());        }    }    public static void login(String name, String[] names) throws NameRepeatException {        for (String string : names) {            if (string.equals(name)) {                throw new NameRepeatException("名字重複了");            }        }    }}

異常使用可遵循下面的原則:

1:在當前方法被覆蓋時,覆蓋他的方法必須拋出相同的異常或異常的子類;2: 在當前方法聲明中使用try-catch語句捕獲異常;3:如果父類拋出多個異常,則覆蓋方法必須拋出那些異常的一個子集,不能拋出新異常。

 

15. Java異常處理

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.