您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“Java基礎(chǔ)之異常處理的方法是什么”的有關(guān)知識,在實(shí)際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
異常是程序中的一些錯誤,但并不是所有的錯誤都是異常,并且錯誤有時候是可以避免的。比如說,你的代碼少了一個分號,那么運(yùn)行出來結(jié)果是提示是錯誤 java.lang.Error;如果你用System.out.println(11/0),那么你是因?yàn)槟阌?做了除數(shù),會拋出 java.lang.ArithmeticException 的異常。
異常發(fā)生的原因有很多,通常包含以下幾大類:
用戶輸入了非法數(shù)據(jù)。
要打開的文件不存在。
網(wǎng)絡(luò)通信時連接中斷,或者JVM內(nèi)存溢出。
這些異常有的是因?yàn)橛脩翦e誤引起,有的是程序錯誤引起的,還有其它一些是因?yàn)槲锢礤e誤引起的。
要理解Java異常處理是如何工作的,你需要掌握以下三種類型的異常:
檢查性異常:最具代表的檢查性異常是用戶錯誤或問題引起的異常,這是程序員無法預(yù)見的。例如要打開一個不存在文件時,一個異常就發(fā)生了,這些異常在編譯時不能被簡單地忽略。
運(yùn)行時異常:運(yùn)行時異常是可能被程序員避免的異常。與檢查性異常相反,運(yùn)行時異??梢栽诰幾g時被忽略。
錯誤:錯誤不是異常,而是脫離程序員控制的問題。錯誤在代碼中通常被忽略。例如,當(dāng)棧溢出時,一個錯誤就發(fā)生了,它們在編譯也檢查不到的。
所有的異常類是從 java.lang.Exception 類繼承的子類。異常類有兩個主要的子類:IOException 類和 RuntimeException 類。Exception 類是 Throwable 類的子類。除了Exception類外,Throwable還有一個子類Error 。Error 用來指示運(yùn)行時環(huán)境發(fā)生的錯誤。Java 程序通常不捕獲錯誤。錯誤一般發(fā)生在嚴(yán)重故障時,它們在Java程序處理的范疇之外。例如,JVM 內(nèi)存溢出。一般地,程序不會從錯誤中恢復(fù)。
在 Java 內(nèi)置類中(接下來會說明),有大部分常用檢查性和非檢查性異常。
Java 語言定義了一些異常類在 java.lang 標(biāo)準(zhǔn)包中。標(biāo)準(zhǔn)運(yùn)行時異常類的子類是最常見的異常類。由于 java.lang 包是默認(rèn)加載到所有的 Java 程序的,所以大部分從運(yùn)行時異常類繼承而來的異常都可以直接使用。
Java 根據(jù)各個類庫也定義了一些其他的異常,下面的表中列出了 Java 的非檢查性異常:
ArithmeticException —— 當(dāng)出現(xiàn)異常的運(yùn)算條件時,拋出此異常。例如,一個整數(shù)"除以零"時,拋出此類的一個實(shí)例。
ArrayIndexOutOfBoundsException —— 用非法索引訪問數(shù)組時拋出的異常。如果索引為負(fù)或大于等于數(shù)組大小,則該索引為非法索引。
ArrayStoreException —— 試圖將錯誤類型的對象存儲到一個對象數(shù)組時拋出的異常。
ClassCastException —— 當(dāng)試圖將對象強(qiáng)制轉(zhuǎn)換為不是實(shí)例的子類時,拋出該異常。
IllegalArgumentException —— 拋出的異常表明向方法傳遞了一個不合法或不正確的參數(shù)。
IllegalMonitorStateException —— 拋出的異常表明某一線程已經(jīng)試圖等待對象的監(jiān)視器,或者試圖通知其他正在等待對象的監(jiān)視器而本身沒有指定監(jiān)視器的線程。
IllegalStateException —— 在非法或不適當(dāng)?shù)臅r間調(diào)用方法時產(chǎn)生的信號。換句話說,即 Java 環(huán)境或 Java 應(yīng)用程序沒有處于請求操作所要求的適當(dāng)狀態(tài)下。
IllegalThreadStateException —— 線程沒有處于請求操作所要求的適當(dāng)狀態(tài)時拋出的異常。
IndexOutOfBoundsException —— 指示某排序索引(例如對數(shù)組、字符串或向量的排序)超出范圍時拋出。
NegativeArraySizeException —— 如果應(yīng)用程序試圖創(chuàng)建大小為負(fù)的數(shù)組,則拋出該異常。
NullPointerException —— 當(dāng)應(yīng)用程序試圖在需要對象的地方使用 null 時,拋出該異常。
NumberFormatException —— 當(dāng)應(yīng)用程序試圖將字符串轉(zhuǎn)換成一種數(shù)值類型,但該字符串不能轉(zhuǎn)換為適當(dāng)格式時,拋出該異常。
SecurityException —— 由安全管理器拋出的異常,指示存在安全侵犯。
StringIndexOutOfBoundsException —— 此異常由 String 方法拋出,指示索引或者為負(fù),或者超出字符串的大小。
UnsupportedOperationException —— 當(dāng)不支持請求的操作時,拋出該異常。
下面的表中列出了 Java 定義在 java.lang 包中的檢查性異常類。
ClassNotFoundException —— 應(yīng)用程序試圖加載類時,找不到相應(yīng)的類,拋出該異常。
CloneNotSupportedException —— 當(dāng)調(diào)用 Object 類中的 clone 方法克隆對象,但該對象的類無法實(shí)現(xiàn) Cloneable 接口時,拋出該異常。
IllegalAccessException —— 拒絕訪問一個類的時候,拋出該異常。
InstantiationException —— 當(dāng)試圖使用 Class 類中的 newInstance 方法創(chuàng)建一個類的實(shí)例,而指定的類對象因?yàn)槭且粋€接口或是一個抽象類而無法實(shí)例化時,拋出該異常。
InterruptedException —— 一個線程被另一個線程中斷,拋出該異常。
NoSuchFieldException —— 請求的變量不存在。
NoSuchMethodException —— 請求的方法不存在。
下面的列表是 Throwable 類的主要方法:
序號 | 方法及說明 |
---|---|
1 | public String getMessage(),返回關(guān)于發(fā)生的異常的詳細(xì)信息。這個消息在Throwable 類的構(gòu)造函數(shù)中初始化了 |
2 | public Throwable getCause(),返回一個 Throwable 對象代表異常原因 |
3 | public String toString(),返回此 Throwable 的簡短描述 |
4 | public void printStackTrace(),將此 Throwable 及其回溯打印到標(biāo)準(zhǔn)錯誤流 |
5 | public StackTraceElement [] getStackTrace(),返回一個包含堆棧層次的數(shù)組。下標(biāo)為0的元素代表?xiàng)m?,最后一個元素代表方法調(diào)用堆棧的棧底 |
6 | public Throwable fillInStackTrace(),用當(dāng)前的調(diào)用棧層次填充Throwable 對象棧層次,添加到棧層次任何先前信息中 |
使用 try 和 catch 關(guān)鍵字可以捕獲異常。try/catch 代碼塊放在異常可能發(fā)生的地方。try/catch代碼塊中的代碼稱為保護(hù)代碼,使用 try/catch 的語法如下:
try { // 程序代碼 }catch(ExceptionName e1) { //Catch 塊 }
Catch 語句包含要捕獲異常類型的聲明。當(dāng)保護(hù)代碼塊中發(fā)生一個異常時,try 后面的 catch 塊就會被檢查。如果發(fā)生的異常包含在 catch 塊中,異常會被傳遞到該 catch 塊,這和傳遞一個參數(shù)到方法是一樣。try/catch 語句使用實(shí)例如下:
// 文件名 : ExcepTest.java import 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"); } } // 以上代碼編譯運(yùn)行輸出結(jié)果如下: // Exception thrown :java.lang.ArrayIndexOutOfBoundsException: 3 // Out of the block
多重捕獲塊:一個 try 代碼塊后面跟隨多個 catch 代碼塊的情況就叫多重捕獲。多重捕獲塊的語法如下所示:
try{ // 程序代碼 }catch(異常類型1 異常的變量名1){ // 程序代碼 }catch(異常類型2 異常的變量名2){ // 程序代碼 }catch(異常類型3 異常的變量名3){ // 程序代碼 }
上面的代碼段包含了 3 個 catch塊。可以在 try 語句后面添加任意數(shù)量的 catch 塊。如果保護(hù)代碼中發(fā)生異常,異常被拋給第一個 catch 塊。如果拋出異常的數(shù)據(jù)類型與 ExceptionType1 匹配,它在這里就會被捕獲。如果不匹配,它會被傳遞給第二個 catch 塊。如此,直到異常被捕獲或者通過所有的 catch 塊。實(shí)例展示了怎么使用多重 try/catch :
try { file = new FileInputStream(fileName); x = (byte) file.read(); } catch(FileNotFoundException f) { // Not valid! f.printStackTrace(); return -1; } catch(IOException i) { i.printStackTrace(); return -1; }
在Java中, throw 和 throws 關(guān)鍵字是用于處理異常的。throw 關(guān)鍵字用于在代碼中拋出異常,而 throws 關(guān)鍵字用于在方法聲明中指定可能會拋出的異常類型。
throw 關(guān)鍵字:用于在當(dāng)前方法中拋出一個異常。通常情況下,當(dāng)代碼執(zhí)行到某個條件下無法繼續(xù)正常執(zhí)行時,可以使用 throw 關(guān)鍵字拋出異常,以告知調(diào)用者當(dāng)前代碼的執(zhí)行狀態(tài)。例如,下面的代碼中,在方法中判斷 num 是否小于 0,如果是,則拋出一個 IllegalArgumentException 異常:
public void checkNumber(int num) { if (num < 0) { throw new IllegalArgumentException("Number must be positive"); } }
throws 關(guān)鍵字:用于在方法聲明中指定該方法可能拋出的異常。當(dāng)方法內(nèi)部拋出指定類型的異常時,該異常會被傳遞給調(diào)用該方法的代碼,并在該代碼中處理異常。例如,下面的代碼中,當(dāng) readFile 方法內(nèi)部發(fā)生 IOException 異常時,會將該異常傳遞給調(diào)用該方法的代碼。在調(diào)用該方法的代碼中,必須捕獲或聲明處理 IOException 異常:
public void readFile(String filePath) throws IOException { BufferedReader reader = new BufferedReader(new FileReader(filePath)); String line = reader.readLine(); while (line != null) { System.out.println(line); line = reader.readLine(); } reader.close(); }
一個方法可以聲明拋出多個異常,多個異常之間用逗號隔開。例如,下面的方法聲明拋出 RemoteException 和 InsufficientFundsException:
import java.io.*; public class className { public void withdraw(double amount) throws RemoteException, InsufficientFundsException { // Method implementation } //Remainder of class definition }
finally 關(guān)鍵字用來創(chuàng)建在 try 代碼塊后面執(zhí)行的代碼塊。無論是否發(fā)生異常,finally 代碼塊中的代碼總會被執(zhí)行。在 finally 代碼塊中,可以運(yùn)行清理類型等收尾善后性質(zhì)的語句。finally 代碼塊出現(xiàn)在 catch 代碼塊最后,語法如下:
try{ // 程序代碼 }catch(異常類型1 異常的變量名1){ // 程序代碼 }catch(異常類型2 異常的變量名2){ // 程序代碼 }finally{ // 程序代碼 }
finally 關(guān)鍵字使用實(shí)例:
public class ExcepTest{ public static void main(String args[]){ int a[] = new int[2]; try{ System.out.println("Access element three :" + a[3]); }catch(ArrayIndexOutOfBoundsException e){ System.out.println("Exception thrown :" + e); } finally{ a[0] = 6; System.out.println("First element value: " +a[0]); System.out.println("The finally statement is executed"); } } } // 實(shí)例編譯運(yùn)行結(jié)果如下: // Exception thrown :java.lang.ArrayIndexOutOfBoundsException: 3 // First element value: 6 // The finally statement is executed
捕獲異常注意下面事項(xiàng):
catch 不能獨(dú)立于 try 存在。
在 try/catch 后面添加 finally 塊并非強(qiáng)制性要求的。
try 代碼后不能既沒 catch 塊也沒 finally 塊。
try, catch, finally 塊之間不能添加任何代碼。
JDK7 之后,Java 新增的 try-with-resource 語法糖來打開資源,并且可以在語句執(zhí)行完畢后確保每個資源都被自動關(guān)閉(注意:try-with-resources 語句關(guān)閉所有實(shí)現(xiàn) AutoCloseable 接口的資源)。JDK7 之前所有被打開的系統(tǒng)資源,比如流、文件或者 Socket 連接等,都需要被開發(fā)者手動關(guān)閉,否則將會造成資源泄露。try-with-resources語法如下:
// 語法中 try 用于聲明和實(shí)例化資源,catch 用于處理關(guān)閉資源時可能引發(fā)的所有異常 try (resource declaration) { // 使用的資源 } catch (ExceptionType e1) { // 異常塊 }
try-with-resources 語句使用實(shí)例:
import java.io.*; public class RunoobTest { public static void main(String[] args) { String line; try(BufferedReader br = new BufferedReader(new FileReader("test.txt"))) { while ((line = br.readLine()) != null) { System.out.println("Line =>"+line); } } catch (IOException e) { System.out.println("IOException in try block =>" + e.getMessage()); } } } // 實(shí)例輸出結(jié)果為: // IOException in try block =>test.txt (No such file or directory)
以上實(shí)例中,我們實(shí)例一個 BufferedReader 對象從 test.txt 文件中讀取數(shù)據(jù)。 在 try-with-resources 語句中聲明和實(shí)例化 BufferedReader 對象,執(zhí)行完畢后實(shí)例資源,不需要考慮 try 語句是正常執(zhí)行還是拋出異常。如果發(fā)生異常,可以使用 catch 來處理異常。
再看下不使用 try-with-resources 而改成 finally 來關(guān)閉資源,整體代碼量多了很多,而且更復(fù)雜繁瑣了:
import java.io.*; class RunoobTest { public static void main(String[] args) { BufferedReader br = null; String line; try { System.out.println("Entering try block"); br = new BufferedReader(new FileReader("test.txt")); while ((line = br.readLine()) != null) { System.out.println("Line =>"+line); } } catch (IOException e) { System.out.println("IOException in try block =>" + e.getMessage()); } finally { System.out.println("Entering finally block"); try { if (br != null) { br.close(); } } catch (IOException e) { System.out.println("IOException in finally block =>"+e.getMessage()); } } } } // 實(shí)例輸出結(jié)果為: // Entering try block // IOException in try block =>test.txt (No such file or directory) // Entering finally block
try-with-resources 處理多個資源:try-with-resources 語句中可以聲明多個資源,方法是使用分號 ; 分隔各個資源:
import java.io.*; import java.util.*; class RunoobTest { public static void main(String[] args) throws IOException{ try (Scanner scanner = new Scanner(new File("testRead.txt")); PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) { while (scanner.hasNext()) { writer.print(scanner.nextLine()); } } } }
以上實(shí)例使用 Scanner 對象從 testRead.txt 文件中讀取一行并將其寫入新的 testWrite.txt 文件中。多個聲明資源時,try-with-resources 語句以相反的順序關(guān)閉這些資源。 在本例中,PrintWriter 對象先關(guān)閉,然后 Scanner 對象關(guān)閉。
在 Java 中你可以自定義異常。編寫自己的異常類時需要記住下面的幾點(diǎn):
所有異常都必須是 Throwable 的子類。
如果希望寫一個檢查性異常類,則需要繼承 Exception 類。
如果你想寫一個運(yùn)行時異常類,那么需要繼承 RuntimeException 類。
可以像下面這樣定義自己的異常類:
class MyException extends Exception{ }
只繼承Exception 類來創(chuàng)建的異常類是檢查性異常類。一個異常類和其它任何類一樣,包含有變量和方法。下面的 InsufficientFundsException 類是用戶定義的異常類,它繼承自 Exception 。
自定義異常實(shí)例:\color{red}{自定義異常實(shí)例 :}自定義異常實(shí)例:
public class BankDemo { public static void main(String[] args) { // 創(chuàng)建賬戶類對象 CheckingAccount c = new CheckingAccount(101); System.out.println("Depositing $500..."); // 存錢 c.deposit(500.00); try { //取錢 System.out.println("\nWithdrawing $100..."); c.withdraw(100.00); //取錢 System.out.println("\nWithdrawing $600..."); c.withdraw(600.00); }catch(InsufficientFundsException e) { //取錢異常,賬戶差額 System.out.println("Sorry, but you are short $" + e.getAmount()); e.printStackTrace(); } } } /** * 自定義異常類 * */ class InsufficientFundsException extends Exception { //此處的amount用來儲存當(dāng)出現(xiàn)異常(取出錢多于余額時)所缺乏的錢 private double amount; public InsufficientFundsException(double amount) { this.amount = amount; } public double getAmount() { return amount; } } /** * 賬戶類 */ class CheckingAccount { //balance為余額,number為卡號 private double balance; private int number; // 構(gòu)造方法 public CheckingAccount(int number) { this.number = number; } //方法:存錢 public void deposit(double amount) { balance += amount; } //方法:取錢 public void withdraw(double amount) throws InsufficientFundsException { if(amount <= balance) { balance -= amount; } else { double needs = amount - balance; throw new InsufficientFundsException(needs); } } //方法:返回余額 public double getBalance() { return balance; } //方法:返回卡號 public int getNumber() { return number; } } // 運(yùn)行程序 BankDemo,得到結(jié)果如下所示: // Depositing $500... // Withdrawing $100... // Withdrawing $600... // Sorry, but you are short $200.0 // InsufficientFundsException // at CheckingAccount.withdraw(MammalInt.java:64) // at MammalInt.main(MammalInt.java:15)
在Java中定義了兩種類型的異常和錯誤:
JVM(Java虛擬機(jī)) 異常:由 JVM 拋出的異?;蝈e誤。例如:NullPointerException 類,ArrayIndexOutOfBoundsException 類,ClassCastException 類。
程序級異常:由程序或者API程序拋出的異常。例如 IllegalArgumentException 類,IllegalStateException 類。
“Java基礎(chǔ)之異常處理的方法是什么”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。