異常是一個(gè)程序執(zhí)行過(guò)程中出現(xiàn)的問(wèn)題。引起異常的原因包括以下幾點(diǎn):
一些異常是由于用戶的錯(cuò)誤,也有是因?yàn)槌绦騿T的錯(cuò)誤,還有是因?yàn)橐恍┪锢碣Y源在某些形式上的錯(cuò)誤。
在 Java 中了解異常處理,您需要了解異常的三個(gè)類別:
所有的異常類都是 java.lang.Exception 類的子類型。異常類都是 Throwable 類的子類。除了異常類 Error 類也是由 Throwable 類產(chǎn)生的的子類。
錯(cuò)誤一般不會(huì)由 Java 程序解決。這些條件通常是在 Java 程序解決不了的錯(cuò)誤出現(xiàn)時(shí)才會(huì)發(fā)生。 Errors 用來(lái)去指示那些運(yùn)行時(shí)環(huán)境生成的錯(cuò)誤。舉例說(shuō)明:JVM(java虛擬機(jī))是不在內(nèi)存中的。一般程序不能從錯(cuò)誤中恢復(fù)。
Exception 類含有兩個(gè)子類:IOException 類和 RuntimeException 類。
http://wiki.jikexueyuan.com/project/java/images/exceptions.jpg" alt="image" />
下面是 Throwable 類的重要方法列表。
SN | 方法描述 |
---|---|
1 | public String getMessage() 返回關(guān)于發(fā)生異常的細(xì)節(jié)信息,這些信息在Throwable的構(gòu)造函數(shù)中被初始化 |
2 | public Throwable getCause() 返回發(fā)生異常的原因,由 Throwable 對(duì)象來(lái)表示 |
3 | public String toString() 返回與getMessage()的結(jié)果相聯(lián)系的類的名稱 |
4 | public void printStackTrace() 打印 toString()跟蹤錯(cuò)誤輸出流的棧地址的結(jié)果。 |
5 | public StackTraceElement [] getStackTrace() 返回一個(gè)數(shù)組,其中包含每個(gè)元素在棧的地址。元素的索引0代表調(diào)用棧的頂部,最后一個(gè)元素表示方法調(diào)用棧的底部。 |
6 | public Throwable fillInStackTrace() 用當(dāng)前棧地址來(lái)填充 Throwable 對(duì)象的棧地址,添加到任何先前的棧地址信息。 |
一個(gè)方法用關(guān)鍵字 try 和 catch 來(lái)捕獲異常。一個(gè) try/catch 塊放置在可能產(chǎn)生異常的代碼外。在 try/catch 塊內(nèi)的代碼是被保護(hù)的,并且其語(yǔ)法如下:
try
{
//Protected code
}catch(ExceptionName e1)
{
//Catch block
}
關(guān)于 catch 的聲明,你必須要指明你要捕獲的異常的類型。如果受保護(hù)的代碼中發(fā)生異常,跟在 try 后面的 catch 塊會(huì)被檢測(cè)。如果異常類型在 catch 中出現(xiàn)了,那么這個(gè)異常會(huì)被傳遞到 catch 當(dāng)中,就像實(shí)參傳遞到方法參數(shù)當(dāng)中。
下面的例子聲明了一個(gè)含有兩個(gè)元素的數(shù)組。然后代碼試圖訪問(wèn)數(shù)組的第三個(gè)元素,這將拋出一個(gè)異常。
// File Name : 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");
}
}
這將產(chǎn)生如下的結(jié)果
Exception thrown :java.lang.ArrayIndexOutOfBoundsException: 3
Out of the block
一個(gè) try 塊可以有多個(gè) catch 塊。多個(gè) catch 塊的語(yǔ)法如下:
try
{
//Protected code
}catch(ExceptionType1 e1)
{
//Catch block
}catch(ExceptionType2 e2)
{
//Catch block
}catch(ExceptionType3 e3)
{
//Catch block
}
前面的語(yǔ)句演示三個(gè) catch 塊,但是你可以在一個(gè) try 后面跟任意數(shù)量的 catch 塊。當(dāng)被保護(hù)代碼中出現(xiàn)異常時(shí),異常首先會(huì)被第一個(gè) catch 塊抓住,如果該異常類型在第一個(gè) catch 塊中列出,便在第一個(gè) catch 塊中被捕獲。如果沒(méi)有列出,便依次向下一個(gè) catch 塊中去匹配,直到找到該異常類型。最后不論是否找到現(xiàn)有的方法都會(huì)停止執(zhí)行,并且拋出異常到上一個(gè)方法的棧地址。
下面是代碼段顯示如何使用多個(gè) try/catch 語(yǔ)句。
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;
}
如果一個(gè)方法不能處理檢測(cè)異常,那么該方法必須用關(guān)鍵字 throws 來(lái)聲明。throws 關(guān)鍵字在方法簽名的最后出現(xiàn)。
你可以通過(guò)關(guān)鍵字 throw 來(lái)拋出一個(gè)異?;蜻M(jìn)行你剛捕獲到的異常的實(shí)例化。試著去理解關(guān)鍵字 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
}
一個(gè)方法可以聲明拋出一個(gè)以上的異常,這些異常用逗號(hào)分隔。例如,下面的方法聲明拋出 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 后面的代碼塊,finally 代碼塊總是會(huì)被執(zhí)行的,不管是怎樣的異常發(fā)生。
使用 finally 塊允許你運(yùn)行您想要執(zhí)行的任何 cleanup-type 語(yǔ)句,無(wú)論在受保護(hù)的代碼中發(fā)生什么。
finally 代碼塊出現(xiàn)在最后一個(gè) catch 塊之后并且語(yǔ)法如下:
try
{
//Protected code
}catch(ExceptionType1 e1)
{
//Catch block
}catch(ExceptionType2 e2)
{
//Catch block
}catch(ExceptionType3 e3)
{
//Catch block
}finally
{
//The finally block always executes.
}
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");
}
}
}
這將產(chǎn)生如下結(jié)果:
Exception thrown :java.lang.ArrayIndexOutOfBoundsException: 3
First element value: 6
The finally statement is executed
以下幾點(diǎn)需要注意:
你可以在 Java 中創(chuàng)建自己的異常。編寫自己的異常類,要記住以下幾點(diǎn):
我們?nèi)缦驴梢远x自己的異常類:
class MyException extends Exception{
}
你只需要繼承 Exception 類來(lái)創(chuàng)建你自己的異常類。這些被認(rèn)為是檢測(cè)異常。以下 InsufficientFundsException 類是一個(gè)用戶定義的異常,同樣繼承了 Exception 類,成為檢測(cè)異常。一個(gè)異常類和任何其他類一樣,包含字段和方法。
例子:
// File Name InsufficientFundsException.java
import java.io.*;
public class InsufficientFundsException extends Exception
{
private double amount;
public InsufficientFundsException(double amount)
{
this.amount = amount;
}
public double getAmount()
{
return amount;
}
}
為了演示使用用戶定義的異常,下面的 CheckingAccount 類包含一個(gè) withdraw() 方法拋出了一個(gè) InsufficientFundsException 異常。
// File Name CheckingAccount.java
import java.io.*;
public class CheckingAccount
{
private double balance;
private int number;
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;
}
}
下面的 BankDemo 程序演示了調(diào)用 CheckingAccount 的 deposit() 和 withdraw() 方法。
// File Name BankDemo.java
public class BankDemo
{
public static void main(String [] args)
{
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();
}
}
}
編譯上述三個(gè)文件并運(yùn)行 BankDemo,將產(chǎn)生以下結(jié)果:
Depositing $500...
Withdrawing $100...
Withdrawing $600...
Sorry, but you are short $200.0
InsufficientFundsException
at CheckingAccount.withdraw(CheckingAccount.java:25)
at BankDemo.main(BankDemo.java:13)
在 Java 中,可以定義兩種異常和錯(cuò)誤