鍍金池/ 教程/ Java/ Java 異常處理
Java 接口
Java 方法
Java 數(shù)字
Java 條件判斷
Java 異常處理
Java 字符
Java 重寫
Java 網(wǎng)絡(luò)編程
Java 數(shù)據(jù)結(jié)構(gòu)
Java 的對(duì)象和類
Java 多線程
Java 封裝
Java 數(shù)組
Java Applet 基礎(chǔ)
Java 庫(kù)類
Java 抽象
Java 繼承
Java 正則表達(dá)式
Java 描述符的類型
Java 發(fā)送郵件
Java 序列化
Java 泛型
Java 多態(tài)
Java 變量類型
Java 基本數(shù)據(jù)類型
Java 包
Java 快速參考指南
Java 基本運(yùn)算符
Java 概述
Java 字符串
Java 循環(huán)控制
Java 環(huán)境設(shè)置
Java 文件注釋
Java 文件和 I/O
Java 集合
Java 基本語(yǔ)法
Java 日期和時(shí)間

Java 異常處理

異常是一個(gè)程序執(zhí)行過(guò)程中出現(xiàn)的問(wèn)題。引起異常的原因包括以下幾點(diǎn):

  • 用戶輸入無(wú)效的數(shù)據(jù)
  • 用戶打開(kāi)一個(gè)不能被找到的文件
  • 網(wǎng)絡(luò)連接已經(jīng)丟失或 JVM 已經(jīng)耗盡內(nèi)存

一些異常是由于用戶的錯(cuò)誤,也有是因?yàn)槌绦騿T的錯(cuò)誤,還有是因?yàn)橐恍┪锢碣Y源在某些形式上的錯(cuò)誤。

在 Java 中了解異常處理,您需要了解異常的三個(gè)類別:

  • 檢測(cè)異常:一個(gè)已檢測(cè)異常通常是用戶錯(cuò)誤或是一個(gè)程序員不能預(yù)見(jiàn)的錯(cuò)誤,如果一個(gè)文件將要被打開(kāi),但系統(tǒng)找不到這個(gè)文件,異常就會(huì)發(fā)生。這些異常在編譯時(shí)不能被簡(jiǎn)單忽略。
  • 運(yùn)行時(shí)異常:運(yùn)行時(shí)異常是可以被程序語(yǔ)法避免的。不同于檢測(cè)異常,運(yùn)行時(shí)異常在編譯時(shí)可以被忽略。
  • 錯(cuò)誤:這并不是異常,但這不是用戶或程序員可以控制的。錯(cuò)誤經(jīng)常在你的代碼中被忽略因?yàn)槟汜槍?duì)一個(gè)錯(cuò)誤幾乎做不了任何事。比如,如果一個(gè)堆棧溢出發(fā)生時(shí),將會(huì)出現(xiàn)一個(gè)錯(cuò)誤。他們?cè)诰幾g時(shí)也會(huì)被忽略。

異常的層次結(jié)構(gòu)

所有的異常類都是 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è)catch塊

一個(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;
}

throws/throw 關(guān)鍵詞

如果一個(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
}

關(guān)鍵字 finally

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)需要注意:

  • catch 在沒(méi)有 try 關(guān)鍵字的情況下是不能夠出現(xiàn)的。
  • try/catch 語(yǔ)句塊中并不是強(qiáng)制出現(xiàn) finally 塊。
  • try 語(yǔ)句塊不能獨(dú)立存在(即沒(méi)有任何 catch 和 finally 塊)。
  • 在 try catch 和 finally 塊之間是不能出現(xiàn)任何代碼的。

聲明自己的異常

你可以在 Java 中創(chuàng)建自己的異常。編寫自己的異常類,要記住以下幾點(diǎn):

  • 所有的異常必須 Throwable 的子類。
  • 如果你想寫一個(gè)自動(dòng)遵守正確處理或聲明規(guī)則的檢測(cè)異常,需要繼承 Exception 類。
  • 如果你想編寫一個(gè)運(yùn)行時(shí)異常,需要繼承 RuntimeException 類。

我們?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)

常見(jiàn)的異常

在 Java 中,可以定義兩種異常和錯(cuò)誤

  • JVM 異常:這些異常/錯(cuò)誤是由 JVM 在邏輯層上或?qū)iT拋出的。例子: NullPointerException, ArrayIndexOutOfBoundsException, ClassCastException。
  • 程序性異常:這些異常是由應(yīng)用程序或是編寫 API 的程序員明確拋出的,如:IllegalArgumentException, IllegalStateException。
上一篇:Java 重寫下一篇:Java 抽象