packagetestexcrpltiom;?
importjava.text.ParseException;?
importjava.text.SimpleDateFormat;?
importjava.util.Scanner;?
importcn.zdsoft.test.Test2;?
importmyutils.MyUtils;?
/**?
?* 測試異常?
?* @author Administrator?
?*?
?*/
publicclassTestException?
{?? Test test;?
????publicstaticvoidmain(String[] args)?
????{?? //空指針異常?
????????//Test.getName();?
????????//算術異常?
????????//System.out.println(1/0);?
????????//下標越界異常?
????????//int [] a={1,2,3};?
????????//System.out.println(a[3]);?
????????//類型轉換異常?
????????//Object obj=new TestException();?
????????//String str=(String)obj;?
????????String str="2013-11-22";?
????????SimpleDateFormat sdf=newSimpleDateFormat("yyyy-MM-dd");?
????????try
????????{?? //放入可能有異常的代碼 可以多條?
????????????sdf.parse(str);?
????????}// eatch 可以有多個來定義不同類型的 異常??
????????catch(ParseException e)?
????????{?
????????????//對捕獲到的異常進行什么樣的處理?
????????????e.printStackTrace();?
????????}//可以加可以不加? 但是只能跟在try catch 后面 且只能有一個? 作用不管有沒有異常都要執行里面的代碼?
????????finally
????????{?
? ? ? ?}?
????}?
}
package testexcrpltiom;
//自定義一個異常類 需要繼承Exception 或者runtimeException
public class CousonException extends Exception
{
//無參構造器
public CousonException()
{//異常的提示語句
this("余額不足");
}
//有參構造器
public CousonException(String str)
{//調用了父類的有參構造器將提示傳上去
super(str);
}
}
*創建一個運行時的異常 需要繼承RuntimeException
*/
public class TestRuntimeException extends RuntimeException
{//定義一個無參構造器用來調用有參構造器來傳遞 提示
public TestRuntimeException()
{
this("你的錢不夠啊");
}
public TestRuntimeException(String str)
{//將提示內容傳遞給父類的有參構造器
super(str);
}
}
package testexcrpltiom;
/**
*
* 將異常添加到需要拋出異常的地方
*
*/
public class Mai
{//在需要拋出異常的方法中要先聲明要拋出的異常類型
public void mai(double m)throws CousonException
{
if(m-90<0)
{//在實際要拋出異常的地方在throw 進行異常的拋出
throw new CousonException();
}
}
}
Java異常學習心得
Java 異常學習心得
本文重在 Java 中異常機制的一些概念。寫本文的目的在于方便我很長時間后若是忘了這些東西可以通過這片文章迅速回憶起來。
1. 異常機制
1.1
異常機制是指當程序出現錯誤后,程序如何處理。具體來說,異常機制提供了程序退出的安全通道。當出現錯誤后,程序執行的流程發生改變,程序的控制權轉移到異常處理器。
1.2
傳統的處理異常的辦法是,函數返回一個特殊的結果來表示出現異常(通常這個特殊結果是大家約定俗稱的),調用該函數的程序負責檢查并分析函數返回的結果。這樣做有如下的弊端:例如函數返回 -1 代表出現異常,但是如果函數確實要返回 -1 這個正確的值時就會出現混淆;可讀性降低,將程序代碼與處理異常的代碼混爹在一起;由調用函數的程序來分析錯誤,這就要求客戶程序員對庫函數有很深的了解。
1.3 異常處理的流程
1.3.1 遇到錯誤,方法立即結束,并不返回一個值;同時,拋出一個異常對象
1.3.2 調用該方法的程序也不會繼續執行下去,而是搜索一個可以處理該異常的異常處理器,并執行其中的代碼
2 異常的分類
2.1 異常的分類
2.1.1
異常的繼承結構:基類為 Throwable , Error 和 Exception 繼承 Throwable , RuntimeException 和 IOException 等繼承 Exception ,具體的 RuntimeException 繼承 RuntimeException 。
2.1.2
Error 和 RuntimeException 及其子類成為未檢查異常( unchecked ),其它異常成為已檢查異常( checked )。
2.2 每個類型的異常的特點
2.2.1 Error 體系
Error 類體系描述了 Java 運行系統中的內部錯誤以及資源耗盡的情形。應用程序不應該拋出這種類型的對象(一般是由虛擬機拋出)。如果出現這種錯誤,除了盡力使程序安全退出外,在其他方面是無能為力的。所以,在進行程序設計時,應該更關注 Exception 體系。
2.2.2 Exception 體系
Exception 體系包括 RuntimeException 體系和其他非 RuntimeException 的體系
2.2.2.1 RuntimeException
RuntimeException 體系包括錯誤的類型轉換、數組越界訪問和試圖訪問空指針等等。處理 RuntimeException 的原則是:如果出現 RuntimeException ,那么一定是程序員的錯誤。例如,可以通過檢查數組下標和數組邊界來避免數組越界訪問異常。
2.2.2.2 其他( IOException 等等)
這類異常一般是外部錯誤,例如試圖從文件尾后讀取數據等,這并不是程序本身的錯誤,而是在應用環境中出現的外部錯誤。
2.3 與 C++ 異常分類的不同
2.3.1
其實, Java 中 RuntimeException 這個類名起的并不恰當,因為任何異常都是運行時出現的。(在編譯時出現的錯誤并不是異常,換句話說,異常就是為了解決程序運行時出現的的錯誤)。
2.3.2
C++ 中 logic_error 與 Java 中的 RuntimeException 是等價的,而 runtime_error 與 Java 中非 RuntimeException 類型的異常是等價的。
3 異常的使用方法
3.1 聲明方法拋出異常
3.1.1 語法: throws (略)
3.1.2 為什么要聲明方法拋出異常?
方法是否拋出異常與方法返回值的類型一樣重要。假設方法拋出異常確沒有聲明該方法將拋出異常,那么客戶程序員可以調用這個方法而且不用編寫處理異常的代碼。那么,一旦出現異常,那么這個異常就沒有合適的異常控制器來解決。
3.1.3 為什么拋出的異常一定是已檢查異常?
RuntimeException 與 Error 可以在任何代碼中產生,它們不需要由程序員顯示的拋出,一旦出現錯誤,那么相應的異常會被自動拋出。而已檢查異常是由程序員拋出的,這分為兩種情況:客戶程序員調用會拋出異常的庫函數(庫函數的異常由庫程序員拋出);客戶程序員自己使用 throw 語句拋出異常。遇到 Error ,程序員一般是無能為力的;遇到 RuntimeException ,那么一定是程序存在邏輯錯誤,要對程序進行修改(相當于調試的一種方法);只有已檢查異常才是程序員所關心的,程序應該且僅應該拋出或處理已檢查異常。
3.1.4
注意:覆蓋父類某方法的子類方法不能拋出比父類方法更多的異常,所以,有時設計父類的方法時會聲明拋出異常,但實際的實現方法的代碼卻并不拋出異常,這樣做的目的就是為了方便子類方法覆蓋父類方法時可以拋出異常。
3.2 如何拋出異常
3.2.1 語法: throw (略)
3.2.2 拋出什么異常?
對于一個異常對象,真正有用的信息時異常的對象類型,而異常對象本身毫無意義。比如一個異常對象的類型是 ClassCastException ,那么這個類名就是唯一有用的信息。所以,在選擇拋出什么異常時,最關鍵的就是選擇異常的類名能夠明確說明異常情況的類。
3.2.3
異常對象通常有兩種構造函數:一種是無參數的構造函數;另一種是帶一個字符串的構造函數,這個字符串將作為這個異常對象除了類型名以外的額外說明。
3.2.4
創建自己的異常:當 Java 內置的異常都不能明確的說明異常情況的時候,需要創建自己的異常。需要注意的是,唯一有用的就是類型名這個信息,所以不要在異常類的設計上花費精力。
3.3 捕獲異常
如果一個異常沒有被處理,那么,對于一個非圖形界面的程序而言,該程序會被中止并輸出異常信息;對于一個圖形界面程序,也會輸出異常的信息,但是程序并不中止,而是返回用 Ы 緱媧 ? 硌 ? 分小 ?BR> 3.3.1 語法: try 、 catch 和 finally (略)
控制器模塊必須緊接在 try 塊后面。若擲出一個異常,異常控制機制會搜尋參數與異常類型相符的第一個控制器隨后它會進入那個 catch
從句,并認為異常已得到控制。一旦 catch 從句結束對控制器的搜索也會停止。
3.3.1.1 捕獲多個異常(注意語法與捕獲的順序)(略)
3.3.1.2 finally 的用法與異常處理流程(略)
3.3.2 異常處理做什么?
對于 Java 來說,由于有了垃圾收集,所以異常處理并不需要回收內存。但是依然有一些資源需要程序員來收集,比如文件、網絡連接和圖片等資源。
3.3.3 應該聲明方法拋出異常還是在方法中捕獲異常?
原則:捕捉并處理哪些知道如何處理的異常,而傳遞哪些不知道如何處理的異常
3.3.4 再次拋出異常
3.3.4.1 為什么要再次拋出異常?
在本級中,只能處理一部分內容,有些處理需要在更高一級的環境中完成,所以應該再次拋出異常。這樣可以使每級的異常處理器處理它能夠處理的異常。
3.3.4.2 異常處理流程
對應與同一 try 塊的 catch 塊將被忽略,拋出的異常將進入更高的一級。
4 關于異常的其他問題
4.1 過度使用異常
首先,使用異常很方便,所以程序員一般不再愿意編寫處理錯誤的代碼,而僅僅是簡簡單單的拋出一個異常。這樣做是不對的,對于完全已知的錯誤,應該編寫處理這種錯誤的代碼,增加程序的魯棒性。另外,異常機制的效率很差。
4.2 將異常與普通錯誤區分開
對于普通的完全一致的錯誤,應該編寫處理這種錯誤的代碼,增加程序的魯棒性。只有外部的不能確定和預知的運行時錯誤才需要使用異常。
4.3 異常對象中包含的信息
一般情況下,異常對象唯一有用的信息就是類型信息。但使用異常帶字符串的構造函數時,這個字符串還可以作為額外的信息。調用異常對象的 getMessage() 、 toString() 或者 printStackTrace() 方法可以分別得到異常對象的額外信息、類名和調用堆棧的信息。并且后一種包含的信息是前一種的超集。
用異常來處理錯誤
我們總是試圖避免在軟件程序中錯誤的發生,但是它的存在卻是不幸的實事。無論怎樣,如果你能適當的處理錯誤,將會極大的改善程序的可讀性、可靠性以及可維護性。 Java?編程語言使用異常來處理錯誤。這章主要講述在什么時候和怎樣使用異常來處理錯誤。
什么是異常?
Java 編程語言使用異常機制為程序提供了錯誤處理的能力。一個異常是在程序執行期間發生的一個事件,它使用正常的指令流中斷。
捕獲或指定需求
這段講述捕獲和處理異常。在討論中包括: try,catch 和 finally 程序塊,還有異常鏈和日志。
怎樣拋出異常
這段講述異常拋出語句和 Throwable 類以及它的子類。
有關未檢查的異常爭論
因為 Java 編程語言不要求捕獲或指定運行時異常或錯誤的方法,所以程序員會被誘導來編寫只拋出運行時異常代碼,在這段中我們會解釋為什么不應該被誘導。
異常的好處
在這段中,你將會學到更多的使用異常來管理錯誤優于傳統的錯誤管理技術方面的知識。
什么是異常?
異常( exception )應該是異常事件( exceptional event )的縮寫。
異常定義:異常是一個在程序執行期間發生的事件,它中斷正在執行的程序的正常的指令流。
當在一個方法中發生錯誤的時候,這個方法創建一個對象,并且把它傳遞給運行時系統。這個對象被叫做異常對象,它包含了有關錯誤的信息,這些信息包括錯誤的類型和在程序發生錯誤時的狀態。創建一個錯誤對象并把它傳遞給運行時系統被叫做拋出異常。
一個方法拋出異常后,運行時系統就會試著查找一些方法來處理它。這些處理異常的可能的方法的集合是被整理在一起的方法列表,這些方法能夠被發生錯誤的方法調用。這個方法列表被叫做堆棧調用( call stack ) , 調用方式如下圖所示
運行時系統搜尋包含能夠處理異常的代碼塊的方法所請求的堆棧。這個代碼塊叫做異常處理器,搜尋首先從發生的方法開始,然后依次按著調用方法的倒序檢索調用堆棧。當找到一個相應的處理器時,運行時系統就把異常傳遞給這個處理器。一個異常處理器要適當地考濾拋出的異常對象的類型和異常處理器所處理的異常的類型是否匹配。異常被捕獲以后,異常處理器關閉。如果運行時系統搜尋了這個方法的所有的調用堆棧,而沒有找到相應的異常處理器,如下圖所示,運行進系統將終止執行。
使用異常來管理錯誤比傳統的錯誤管理技術有一些優勢,你可以“異常的優勢”一節學到更多的知識
異常管理的優勢
你已經讀了有關什么是異常以及怎樣使用它們的內容,現在是學習在你的程序中使用異常的好處的時候了。
優勢 1 :把規則代碼與錯誤處理代碼分離
異常處理規定把錯誤發生時所要的細節工作與程序的主邏輯代碼分離。在傳統程序中,錯誤的發現、報告以及處理經常使得代碼混亂。例如,思考下面的偽代碼,這是一個把整個文件讀入內存的方法。
readFile {
open the file;
determine its size;
allocate that much memory;
read the file into memory;
close the file;
}
第一眼看上去,這個函數似乎很簡單,但是它卻忽略了所發生下面這些錯誤的可能。
1、?如果不能打開文件,會發生什么?
2、?如果不能判定文件的大小,會發生什么?
3、?如果沒有足夠的內存,會發生什么?
4、?如果讀取失敗,會發生什么?
5、?如果文件不能關閉。會發生什么?
要處理這些信息, readFile 函數必須用更多的代碼來做錯誤發現、報告和處理工作。這個函數看上去可能象這樣:
errorCodeType readFile {
initialize errorCode = 0;
open the file;
if (theFileIsOpen) {
determine the length of the file;
if (gotTheFileLength) {
allocate that much memory;
if (gotEnoughMemory) {
read the file into memory;
if (readFailed) {
errorCode = -1;
}
else {
errorCode = -2;
}
} else {
errorCode = -3;
}
close the file;
if (theFileDidntClose && errorCode == 0) {
errorCode = -4;
} else {
errorCode = errorCode and -4;
}
} else {
errorCode = -5;
}
return errorCode;
}
有如此多的錯誤發現、報告和返回,使得初的 7 行代碼被埋沒在混亂的錯誤代碼之中。更嚴重的是,代碼的邏輯流已經沒有了,這樣使得它很難說明代碼是否正在做著正確的事情:如果函數在分配內存過程失敗,文件真得的被關閉了嗎?甚至更難保證在三個月之后,你編寫的這段代碼繼續做正確的事情。
異常處理使你能夠編寫代碼的主工作流并且在別的地方來處理異常信息。如果 readFile 函數使用異常處理來代替傳統的錯誤管理技術,它應該像如下所示的代碼這樣:
readFile {
try {
open the file;
determine its size;
allocate that much memory;
read the file into memory;
close the file;
} catch (fileOpenFailed) {
doSomething;
} catch (sizeDeterminationFailed) {
doSomething;
} catch (memoryAllocationFailed) {
doSomething;
} catch (readFailed) {
doSomething;
} catch (fileCloseFailed) {
doSomething;
}
}
注意:異常處理不會節省錯誤的發現、報告、處理的工作量,但是它們能夠幫助你更有效的組織代碼。
優勢 2 :向調用堆棧上層傳遞錯誤
異常處理的第二個優勢是向方法的調用堆棧上層傳遞錯誤報告的能力。假如 readFile 方法是主程序調用的一系列嵌套方法中的第四個方法:方法 1 調用方法 2 ,方法 2 調用方法 3 ,方法 3 調用 readFile ,代碼結構如下所示:
method1 {
call method2;
}
method2 {
call method3;
}
method3 {
call readFile;
}
還假如 method1 是唯一的能夠處理 readFile 方法中所可能發生的錯誤的方法,那么傳統的錯誤處理技術會強制 method2 和 method3 來傳遞通過 readFile 調用堆棧所返回的錯誤代碼,直到錯誤代碼傳遞到 method1 -因為只有 method1 能夠處理這些錯誤,其代碼結構如下所示:
method1 {
errorCodeType error;
error = call method2;
if (error)
doErrorProcessing;
else
proceed;
}
errorCodeType method2 {
errorCodeType error;
error = call method3;
if (error)
return error;
else
proceed;
}
errorCodeType method3 {
errorCodeType error;
error = call readFile;
if (error)
return error;
else
proceed;
}
回憶一下, Java 運行時環境搜尋調用堆棧來查找任意的處理特殊的異常的方法。一個方法能夠拋出它內部的任何異常,所以允許一個上層調用堆棧的方法來捕獲它。因此只有處理相關錯誤的方法來處理發現的錯誤,代碼結構如下所示:
method1 {
try {
call method2;
} catch (exception e) {
doErrorProcessing;
}
}
method2 throws exception {
call method3;
}
method3 throws exception {
call readFile;
}
無論怎樣,就像偽代碼所展示的那樣,躲避異常需要中間方法做一些工作。任意被檢查到的由內部方法的拋出的異常必須在這個方法的 throws 子句中被指定。
優勢 3 :分組和區分錯誤類型
因為所有在程序內部拋出的異常都是對象,異常的分組或分類是類繼承的自然結果。在 Java 平臺中一組相關異常類的例子是在 java.io 中定義的 IOException 和它的子類。 IOException 是最普通的 IO 異常管理類,并且它描述了在執行 I/O 操作時所發生的任意的錯誤類型。它的子類描述了一些特殊的錯誤。例如, FileNotFoundException 異常類代表不能在本地磁盤上找到一個文件。
一個方法能夠編寫特殊的異常處理器,使它能夠處理非常特殊的異常。 FileNotFoundException 異常類沒有子類,因此下面的異常處理器只能處理一種異常類型:
catch (FileNotFoundException e) {
...
}
一個方法能夠基于它的分組或通過在 catch 子句中所指定的任何異常的超類的一般類型來捕獲異常。例如,要捕獲所有的 I/O 異常,而不管它們的具體類型,就可以在異常處理器中指定一個 IOException 參數:
catch (IOException e) {
...
}
這個處理器將捕獲所有的 I/O 異常,包括 FileNotFoundException,EOFException 等等。你能夠通過查詢傳遞給異常處理器的參數找到發生錯誤的詳細信息。例如,打印堆棧執行路線:
catch (IOException e) {
e.printStackTrace(); // output goes to Sytem.err
e.printStackTrace(System.out); // send trace to stdout
}
你甚至可以創建一個能夠處理任意類型的異常的異常處理器:
catch (Exception e) { // a (too) general exception handler
...
}
Exception 類是 Throwable 類結構中的頂級類,因此,這個處理器將捕獲除了那些被特定處理器捕獲的異常以外的異常。你可能想你的程序是否都是這種處理異常的方法,例如,為用戶打印錯誤消息并且退出。
但是,在大多數情況下,你需要異常處理器來盡可能的處理精確一些。原因是在處理器決定最好的恢復策略之前,必須做第一件是判斷發生異常的類型是什么。在沒有捕獲特定錯誤的情況下,處理器必須有效的提供任意的可能性。 Exception 處理器是最一般的異常處理器,使用這個處理器使得代碼捕獲和處理更多的程序員沒有預料到的錯誤傾向,從而使得處理器沒有目的性。
象我們展示的一樣,你能夠創建異常組,并且用一般化的方式來處理異常,或者使用特定異常類型來區分異常并且用精確的方式來處理異常。
捕獲和處理異常
這段向說明怎樣使用異常處理器的三個組成部分- try,catch 和 finally 塊來編寫異常處理器。這段最后舉一個例子,并且分析在不同的情況下發生了什么。
下面的例子定義和實現了一個叫做 ListOfNumbers 的類。在類的構造器中, ListOfNumbers 創建了一個 Vector ,它包含了從 0 到 9 的十個連續的整數。 ListOfNumbers 類也定義了一個叫 writeList 的方法,這個方法把這個數字列表寫入一個叫做 OutFile.txt 的文本文件中。這個例子使用了在 java.io 中定義的輸出類,這個類在 I/O :讀寫這一章中介紹。
// 注意 : 這樣的設計,這個類不會被編譯
import java.io.*;
import java.util.Vector;
public class ListOfNumbers {
private Vector victor;
private static final int SIZE = 10;
public ListOfNumbers () {
victor = new Vector(SIZE);
for (int i = 0; i < SIZE; i++) {
victor.addElement(new Integer(i));
}
}
public void writeList() {
PrintWriter out = new PrintWriter(
new FileWriter("OutFile.txt"));
for (int i = 0; i < SIZE; i++) {
out.println("Value at: " + i + " = " +
victor.elementAt(i));
}
out.close();
}
}
這個例子中的第一行黑體字部分代碼調用了一個構造器,這個構造器初始化一個文件輸出流。如果這個文件不能被打開,這個構造器會拋出一個 IOException 異常。第二行黑體字部分代碼調用一個 Vector 類的 elementAt 方法,如果它的參數值太小(小于零)或太大(大于 Vector 中當前所包含的元素數),那么它會拋出一個 ArrayIndexOutOfBoundsException 異常。
如果試圖編譯 ListOfNumbers 類,編譯會打印一個有關被 FileWrite 構造器所拋出的異常的錯誤消息。這是因為構造所拋出的 IOException 異常是一個編譯檢查性異常,被 elementAt 方法拋出的 ArrayIndexOutOfBoundsException 異常是一個運行時異常,而 Java 編程語言只要求程序處理編譯檢查性異常,所以你只能獲取一個錯誤消息。
現在隨著對 ListOfNumbers 類的熟悉,并且知道異常是在程序中的什么地方拋出的,那么你就可以準備把異常處理器編寫到 catch 塊來處理那些異常。
怎樣拋出異常
在你能夠捕捉一個異常之前,在程序中的某個地方必須有拋出這個異常的代碼在在。任何代碼都可以拋出異常:它們可以你自己的代碼,也可以是來自于別人所寫的包中的代碼(例如與 Java 平臺一起提供的程序包),或者是 Java 運行時環境。不管拋出什么樣的異常,都要使用 throw 語句把異常拋出。
你可能已經注意到, Java 平臺提供了各種的異常類。所有的這些類都是 Throwable 類的子類,并且它們都允許程序來區分在程序執行期間所發生的各種類型的異常。
你也可以創建自己的異常類來描述你編寫的類中所發生的問題。實際上,如果你是一個程序包的開發人員,你可能必須創建你自己的異常類的集合,以便于讓你的用戶來區分在你的程序包中發生的錯誤是來自己于 Java 平臺還是其它的包。
你也可以創建異常鏈,異常鏈在 Java Standard Edition 1.4 中被引入。更多的信息,請看“異常鏈”這一節。
“ throw ”語句
所有的方法都使用“ throw ”語句來拋出一個異常。 Throw 語句需要一個單獨 throwable 對象,這個對象是任意 Throwable 類的子類。如下類所示:
throw someThrowableObject;
讓我們在程序的上下文中來看一下 throw 語句。下面的 pop 方法把來自于一個公共堆棧中的一個執行類給刪除。這個方法從堆棧上面的元素,并且返回被刪除的對象。
public Object pop() throws EmptyStackException {
Object obj;
if (size == 0) {
throw new EmptyStackException();
}
obj = objectAt(SIZE - 1);
setObjectAt(SIZE - 1, null);
size--;
return obj;
}
pop 方法檢查堆棧上是否有元素。如果堆棧是空的(也就是說它的尺寸等于 0 ), pop 方法就會實例化一個新的 EmptyStackException 對象(它是 java.util 中的一個成員),并且拋出它。在這章的后面一節會解釋怎樣創建自己的異常類。對于現在,你所需要記住的是你只能拋出繼承于 java.lang.Throwable 類的對象。
注意, pop 方法的聲明中包含了一個 throws 子句。 EmptyStackException 是一個檢查性異常,并且 pop 方法沒有捕捉這個異常。因此,這個方法必須使用 throws 子名來聲明它所拋出的異常的類型。
Throwable 類和它的子類
繼承 Throwable 類的對象包括直接子類(直接繼承于 Throwable 類的對象)和間接子類(繼承于 Throwable 類的子類的對象)。下圖說明了 Throwable 類的層次關系和最主要的一些子類。象你看到的一樣, Throws 有兩個直接的子類: Error 類和 Exception 類。
Error 類
當在 Java 虛擬機中發生動態連接失敗或其它的定位失敗的時候, Java 虛擬機拋出一個 Error 對象。典型的簡易程序不捕獲或拋出 Errors 對象。
Exception 類
大多數程序都拋出或捕獲衍生于 Exception 類的對象。一個異常表明發生了一個問題,但它不是嚴重的系統問題。你編定的大多數程序將會拋出或捕獲 Exceptions 對象(而不是 Errors 對象)。
在 Java 平臺中 Exception 類有許多已經定義了的子類。這些子類說明所發生的異常的各種類型。例如, IllegalAccessException 異常類說明了不能找到一個特殊的方法; NegativeArraySizeException 異常類說明程序試圖創建一個帶有負尺寸的數組。
有一個特殊的 Exception 子類: RuntimeException 。這個子類是在程序運行期間在 Java 虛擬機內部所發生的異常。例如 NullPointerException 類就是一個運行時異常類,在一個方法試圖通過一個 null 引用來訪問一個對象的成員時會發生這個異常。在 Unchecked Exceptions---The Controversy 這一節中,我們會討論為什么典型的程序不應該拋出運行時異常或 RuntimException 類的子類異常對象。
有爭議性的未被檢查的異常
因為 Java 編程語言不要求方法一定要捕獲或列出運行異常或錯誤,所以程序員就可能被誤導,編寫只拋出運行時異常或者使所有的異常子類都繼承于 RuntimException 的代碼,這兩種快捷方式允許程序員編寫不用為編譯錯誤而操心的代碼,并且也不費神去指定或捕獲任何異常。盡管這種方法看上去對程序員很方便,但它回避了捕獲或指定必要的東西的意圖,并且可能使使用你的類的程序員發生錯誤。
為什么設計者決定強制一個方法指定所有的在它的范圍內可能被拋出的未檢查異常呢?被一個方法拋出的任何異常都是方法公共編程接口的一部分。方法的調用者必須知道有關這個方法所拋出的異常,以便他們能夠針對這些異常決定做什么。這些異常是編寫方法的接口差不多,有它們的參數和返回值。
接下來你的問題可能是:如果它是這么好的說明了一個方法的 API ,包括它能拋出的異常,那么為什么不也指定運行時異常呢?運行時異常描述的問題是一個設計問題的結果,并且, API 的客戶代碼不能期望從出錯的地方來恢復程序執行或用一些方法來處理它們。這些問題包括算法異常(例如被零除),指針異常(例如通過一個空的引用來訪問一個對象),以及索引異常(例如試圖通過一個越界的索引來訪問一個數組)。運行時異常可能在
程序的任何地方發生,并且在一個典型的程序中可能有很多,因此,在每個方法中不得不添加運行異常來降低程序的透明度,這樣,編譯器不要求你指定或捕獲運行時異常(盡管你可以)。
拋出運行時異常( RuntimeException )的一個公共案例就是在用戶調用了一個錯誤的方法的時候。例如,一個方法檢查它的參數是否有效,如果一個參數是空( null ),那么這個方法就可能拋出一個 NullPointerException 異常,這是一個不檢查異常。
一般來說,不拋出運行時異常( RuntimeException )或不創建一個運行時異常( RuntimeException )的子類的原因是:人你不想為指定你的方法所能拋出的異常而操心。
一個使用異常的方針是:如果客戶能夠被期望從一個異常中得到恢復,那么就要使用檢查性異常。如果一個客戶對于從異常中恢復的程序不能做任何事,那么就可以使用不檢查性異常。
第一、try語句不能單獨存在,可以和catch、finally組成 try...catch...finally、try...catch、try...finally三種結構,catch語句可以有一個或多個,finally語句最多一個,try、catch、finally這三個關鍵字均不能單獨使用。
第二、try、catch、finally三個代碼塊中變量的作用域分別獨立而不能相互訪問。如果要在三個塊中都可以訪問,則需要將變量定義到這些塊的外面。
第三、多個catch塊時候,Java虛擬機會匹配其中一個異常類或其子類,就執行這個catch塊,而不會再執行別的catch塊。
第四、throw語句后不允許有緊跟其他語句,因為這些沒有機會執行。
第五、如果一個方法調用了另外一個聲明拋出異常的方法,那么這個方法要么處理異常,要么聲明拋出。
異常的概念及分類異常時程序在編譯或運行過程出現的例外,這些例外在有的可以避免有的卻無法避免
檢查異常也稱為編譯期異常 不可避免,必須進行異常處理,要不編譯器報錯
未檢查異常也稱為運行時異常 可以避免,不需要必須處理,通過修改代碼解決
常見的運行異常
NullPointerException空指針異常
ArithmeticException 算術異常
ArrayIndexOutOfBoundsException數組下標越界異常
ClassCastException類型轉換異常
常見的編譯異常
ParseException 解析異常
異常的處理方式
Java編譯期異常必須要進行處理,否則Java源文件在編譯時編譯器會提示錯誤,且源文件無法成功編譯
Java編譯期異常的處理方式有兩種
使用try、catch、finally關鍵字捕獲異常 使用throws關鍵字聲明拋出異常
使用try、catch、finally捕獲異常
try{
//可能會出現異常的代碼
}
catch(ParseException e)
{
//捕獲執行的代碼
}
finally
{
//不管是否發生異常都要執行的代碼
}
自定義異常類
在開發中,可能需要自定義異常類 自定義異常根據繼承的父類不同分為兩類繼承自Exception的自定義異常類
繼承自Exception的自定義異常為編譯期異常必須要進行 處理。
繼承自RuntimeException的自定義異常類
繼承自RuntimeException的自定義異常為運行時異常不需要進行特別的處理。