一、異常的分類
異常具有自己的語法和特定的繼承結(jié)構(gòu)。異常對象都是繼承Throwable類的一個實例。如果java中內(nèi)置的異常類不能滿足需求,用戶也可以創(chuàng)建自己的異常類。

java語言規(guī)范:繼承Error類或RuntimeException的所有異常成為非受查異常,所有其他的異常(IOException)稱為受查異常。編譯器將檢查是否為所有的受查異常提供了異常處理器。
二、每類異常描述的錯誤
其中,每類層次結(jié)構(gòu)描述的錯誤如下:

從圖中可以看出:“如果出現(xiàn)RuntimeException異常,一定是程序的問題”。應該通過檢查數(shù)組的下標是否越界來避免ArryIndexOutOfBoundsException異常;在使用變量時檢查是否為null來杜絕NullPointerException異常的發(fā)生。
三、聲明異常
一個方法不僅需要告訴編譯器將要返回什么值,還要告訴編譯器有可能發(fā)生聲明錯誤。方法應該在首部聲明所有可能拋出的異常,這樣可以從首部反映出這個方法可能拋出哪類受查異常。在編寫方法時,不必將所有可能拋出的異常都進行聲明。
1、需拋出異常的4種情況:
(1)調(diào)用一個拋出受查異常的方法
(2)程序運行過程中發(fā)現(xiàn)錯誤,并且利用throw語句拋出一個受查異常
(3)程序出現(xiàn)錯誤,如,a[-1]會拋出一個ArryIndexOutOfBoundsException這樣的非受查異常
(4)java虛擬機和運行時庫出現(xiàn)的內(nèi)部錯誤
2、聲明受查異常
(1)如果出現(xiàn)上述前2種情況,必須要告訴調(diào)用這個方法的程序員有可能拋出異常。對于那些可能被他人使用的方法,應該根據(jù)異常規(guī)范,在方法的首部聲明這個方法可能拋出的異常。
class MyAnimation
{
......
public Image loadImage(String s) throws IOException
{
......
}
}
(2)如果一個方法有可能拋出多個受查異常類型,必須在方法的首部列出所有的異常類。每個異常類之間用逗號隔開。
class MyAnimation
{
......
public Image loadImage(String s) throws FileNotFoundException,EOFException
{
......
}
}
3、非受查異常不需要聲明
不需要聲明java的內(nèi)部錯誤,即從Error繼承的錯誤(非受查異常)。任何程序代碼都具有拋出那些異常的潛能,而我們對其沒有任何控制能力。同樣,也不應該聲明從RuntimeException繼承的那些非受查異常。因為這些運行時錯誤完全在我們的控制之下。如果特別關注這些引發(fā)的錯誤,就應該將更多的時間花費在修正程序設計上,而不是說明這些錯誤發(fā)生的可能性上。
總之,一個方法必須聲明所有可能拋出的受查異常,而非受查異常要么不可控制(Error),要不就應該避免發(fā)生(RuntimeException)。如果方法沒有聲明所有可能發(fā)生的受查異常,編譯器就會發(fā)出一個錯誤消息。
4、需要注意的是:
(1)如果類中的一個方法聲明將會拋出一個異常時,而這個異常是某個特定類的實例時,則這個方法就有可能拋出一個這個類的異常,或者是這個類的任意一個子類的異常。例:FileInputStream構(gòu)造器聲明將有可能拋出一個IOException異常,然而并不知道具體是哪種IOException異常。它既可以是IOException異常,也可以是其子類的異常,如FileNotFoundIOException。
(2)如果在子類中覆蓋了超類的一個方法,子類方法中聲明的受查異常不能比超類方法中聲明的異常更通用(也就是說,子類方法中可以拋出更特定的異常,或根本不拋出任何異常)。特別要說明的是,如果超類方法沒有拋出任何受查異常,子類也不能拋出任何受查異常。那么子類的受查異常要怎么處理呢?這就涉及到捕獲異常了(見下節(jié))。
四、如何拋出異常
(1)找到一個合適的異常類:如EOFException異常類,繼承IOException
(2)創(chuàng)建這個類的一個對象:
throw new EOFException;或
EOFException e=new EOFException();
throw e;
(3)將對象拋出
String readData(Scanner in) throws EOFException
{
......
while (......)
{
if (!in.hashnext())
{
if (n<len)
throw new EOFException();
}
......
}
return s;
}
一旦方法拋出了異常,這個方法就不可能返回到調(diào)用者。也就是說,不必為返回的默認值或錯誤代碼擔憂。需要注意的是,在java中,只能拋出Throwable子類的對象。
五、創(chuàng)建異常類
在程序中,可能會遇到任何標準異常類都不能充分地描述清楚地問題,在這種情況下可以創(chuàng)建自己地異常類。需要做的只是定義一個繼承Exception的類,或者繼承Exception子類的類,但是創(chuàng)建的異常類實質(zhì)上都被認為是受查異常。習慣上,定義的類應該包括兩個構(gòu)造器,一個是默認的構(gòu)造器,另一個是帶有詳細信息的構(gòu)造器。
class FileFormatException extends IOException
{
public FileFormatException() {}
public FileFormatException(String gripe)
{
super(gripe);
}
}
或
class FileFormatException extends Exception
{
public FileFormatException() {}
public FileFormatException(String gripe)
{
super(gripe);
}
}
用法:聲明創(chuàng)建的異常并拋出:
public void getConfig() throws FileFormatException
{
code
throw new test();
}
如果不聲明,編譯器報錯提示聲明,可見其為受查異常:
public void getConfig()
{
code
throw new test();
}
需要注意的是:標準異常與創(chuàng)建的異常不能混為一談,雖然FileFormatException繼承Exception,但方法的首部也必須要聲明IOException:
下列程序會報錯Unhandled exception type FileNotFoundException:
public void getConfig() throws FileFormatException
{
File filePath = new File(System.getProperty("user.home") + File.separator + "AppiumExecutor" + File.separator + "config1.properties");
InputStream inputStream = new FileInputStream(filePath);
String aa = inputStream.toString();
throw new FileFormatException("我是一個異常");
}
需要這樣寫:
public void getConfig() throws FileFormatException,IOException(或FileNotFoundException)
{
File filePath = new File(System.getProperty("user.home") + File.separator + "AppiumExecutor" + File.separator + "config1.properties");
InputStream inputStream = new FileInputStream(filePath);
String aa = inputStream.toString();
throw new FileFormatException("我是一個異常");
}