Java異常處理

異常是程序中的一些錯誤拍冠,但并不是所有的錯誤都是異常贴妻,并且錯誤有時候是可以避免的涧团。

比如說只磷,你的代碼少了一個分號,那么運行出來結果是提示是錯誤 java.lang.Error泌绣;如果你用System.out.println(11/0)钮追,那么你是因為你用0做了除數(shù),會拋出 java.lang.ArithmeticException 的異常阿迈。

異常發(fā)生的原因有很多元媚,通常包含以下幾大類:

1.用戶輸入了非法數(shù)據(jù)。

2.要打開的文件不存在。

3.網(wǎng)絡通信時連接中斷刊棕,或者JVM內(nèi)存溢出炭晒。

這些異常有的是因為用戶錯誤引起,有的是程序錯誤引起的甥角,還有其它一些是因為物理錯誤引起的网严。-

要理解Java異常處理是如何工作的,你需要掌握以下三種類型的異常:

1.檢查性異常:最具代表的檢查性異常是用戶錯誤或問題引起的異常嗤无,這是程序員無法預見的震束。例如要打開一個不存在文件時,一個異常就發(fā)生了当犯,這些異常在編譯時不能被簡單地忽略垢村。

2.運行時異常: 運行時異常是可能被程序員避免的異常。與檢查性異常相反嚎卫,運行時異臣嗡ǎ可以在編譯時被忽略。

3.錯誤: 錯誤不是異常驰凛,而是脫離程序員控制的問題。錯誤在代碼中通常被忽略担扑。例如恰响,當棧溢出時,一個錯誤就發(fā)生了涌献,它們在編譯也檢查不到的胚宦。

Exception 類的層次

所有的異常類是從 java.lang.Exception 類繼承的子類。

Exception 類是 Throwable 類的子類燕垃。除了Exception類外枢劝,Throwable還有一個子類Error

Java 程序通常不捕獲錯誤。錯誤一般發(fā)生在嚴重故障時卜壕,它們在Java程序處理的范疇之外您旁。

Error 用來指示運行時環(huán)境發(fā)生的錯誤。

例如轴捎,JVM 內(nèi)存溢出鹤盒。一般地,程序不會從錯誤中恢復侦副。

異常類有兩個主要的子類:IOException 類和 RuntimeException 類侦锯。

在 Java 內(nèi)置類中(接下來會說明),有大部分常用檢查性和非檢查性異常秦驯。

Java 內(nèi)置異常類

Java 語言定義了一些異常類在 java.lang 標準包中尺碰。

標準運行時異常類的子類是最常見的異常類。由于 java.lang 包是默認加載到所有的 Java 程序的,所以大部分從運行時異常類繼承而來的異常都可以直接使用亲桥。

Java 根據(jù)各個類庫也定義了一些其他的異常洛心,下面的表中列出了 Java 的非檢查性異常。

異常 描述

ArithmeticException 當出現(xiàn)異常的運算條件時两曼,拋出此異常皂甘。例如,一個整數(shù)"除以零"時悼凑,拋出此類的一個實例偿枕。

ArrayIndexOutOfBoundsException 用非法索引訪問數(shù)組時拋出的異常。如果索引為負或大于等于數(shù)組大小户辫,則該索引為非法索引渐夸。

ArrayStoreException 試圖將錯誤類型的對象存儲到一個對象數(shù)組時拋出的異常。

ClassCastException 當試圖將對象強制轉換為不是實例的子類時渔欢,拋出該異常墓塌。

IllegalArgumentException 拋出的異常表明向方法傳遞了一個不合法或不正確的參數(shù)。

IllegalMonitorStateException 拋出的異常表明某一線程已經(jīng)試圖等待對象的監(jiān)視器奥额,或者試圖通知其他正在等待對象的監(jiān)視器而本身沒有指定監(jiān)視器的線程苫幢。

IllegalStateException 在非法或不適當?shù)臅r間調用方法時產(chǎn)生的信號。換句話說垫挨,即 Java 環(huán)境或 Java 應用程序沒有處于請求操作所要求的適當狀態(tài)下韩肝。

IllegalThreadStateException 線程沒有處于請求操作所要求的適當狀態(tài)時拋出的異常。

IndexOutOfBoundsException 指示某排序索引(例如對數(shù)組九榔、字符串或向量的排序)超出范圍時拋出哀峻。

NegativeArraySizeException 如果應用程序試圖創(chuàng)建大小為負的數(shù)組,則拋出該異常哲泊。

NullPointerException 當應用程序試圖在需要對象的地方使用 null 時剩蟀,拋出該異常

NumberFormatException 當應用程序試圖將字符串轉換成一種數(shù)值類型,但該字符串不能轉換為適當格式時切威,拋出該異常育特。

SecurityException 由安全管理器拋出的異常,指示存在安全侵犯先朦。

StringIndexOutOfBoundsException 此異常由 String 方法拋出且预,指示索引或者為負,或者超出字符串的大小烙无。

UnsupportedOperationException 當不支持請求的操作時锋谐,拋出該異常。

下面的表中列出了 Java 定義在 java.lang 包中的檢查性異常類截酷。


異常 描述

ClassNotFoundException 應用程序試圖加載類時涮拗,找不到相應的類,拋出該異常。

CloneNotSupportedException 當調用 Object 類中的 clone 方法克隆對象三热,但該對象的類無法實現(xiàn) Cloneable 接口時鼓择,拋出該異常。

IllegalAccessException 拒絕訪問一個類的時候就漾,拋出該異常呐能。

InstantiationException 當試圖使用 Class 類中的 newInstance 方法創(chuàng)建一個類的實例,而指定的類對象因為是一個接口或是一個抽象類而無法實例化時抑堡,拋出該異常摆出。

InterruptedException 一個線程被另一個線程中斷,拋出該異常首妖。

NoSuchFieldException 請求的變量不存在

NoSuchMethodException 請求的方法不存在

異常方法

下面的列表是 Throwable 類的主要方法:

序號 方法及說明

1 public String getMessage()

返回關于發(fā)生的異常的詳細信息偎漫。這個消息在Throwable 類的構造函數(shù)中初始化了。

2 public Throwable getCause()

返回一個Throwable 對象代表異常原因有缆。

3 public String toString()

使用getMessage()的結果返回類的串級名字象踊。

4 public void printStackTrace()

打印toString()結果和棧層次到System.err,即錯誤輸出流棚壁。

5 public StackTraceElement [] getStackTrace()

返回一個包含堆棧層次的數(shù)組杯矩。下標為0的元素代表棧頂,最后一個元素代表方法調用堆棧的棧底袖外。

6 public Throwable fillInStackTrace()

用當前的調用棧層次填充Throwable 對象棧層次史隆,添加到棧層次任何先前信息中。

捕獲異常

使用 try 和 catch 關鍵字可以捕獲異常在刺。try/catch 代碼塊放在異衬婧Γ可能發(fā)生的地方头镊。

try/catch代碼塊中的代碼稱為保護代碼蚣驼,使用 try/catch 的語法如下:

```try

{

? // 程序代碼

}catch(ExceptionName e1)

{

? //Catch 塊

}```

Catch 語句包含要捕獲異常類型的聲明。當保護代碼塊中發(fā)生一個異常時相艇,try 后面的 catch 塊就會被檢查颖杏。

如果發(fā)生的異常包含在 catch 塊中,異常會被傳遞到該 catch 塊坛芽,這和傳遞一個參數(shù)到方法是一樣留储。

實例

下面的例子中聲明有兩個元素的一個數(shù)組,當代碼試圖訪問數(shù)組的第三個元素的時候就會拋出一個異常咙轩。

```

ExcepTest.java 文件代碼:

// 文件名 : 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");

? }

}```

以上代碼編譯運行輸出結果如下:

```

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 塊活喊。

如果保護代碼中發(fā)生異常丐膝,異常被拋給第一個 catch 塊。

如果拋出異常的數(shù)據(jù)類型與 ExceptionType1 匹配,它在這里就會被捕獲帅矗。

如果不匹配偎肃,它會被傳遞給第二個 catch 塊。

如此浑此,直到異常被捕獲或者通過所有的 catch 塊累颂。

實例

該實例展示了怎么使用多重 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;

}

```

throws/throw 關鍵字:

如果一個方法沒有捕獲到一個檢查性異常凛俱,那么該方法必須使用 throws 關鍵字來聲明紊馏。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

}

```

一個方法可以聲明拋出多個異常,多個異常之間用逗號隔開暖哨。

例如赌朋,下面的方法聲明拋出 RemoteException 和 InsufficientFundsException:

```

import java.io.*;

public class className

{

? public void withdraw(double amount) throws RemoteException,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? InsufficientFundsException

? {

? ? ? // Method implementation

? }

? //Remainder of class definition

}

```

finally關鍵字

finally 關鍵字用來創(chuàng)建在 try 代碼塊后面執(zhí)行的代碼塊。

無論是否發(fā)生異常篇裁,finally 代碼塊中的代碼總會被執(zhí)行沛慢。

在 finally 代碼塊中,可以運行清理類型等收尾善后性質的語句达布。

finally 代碼塊出現(xiàn)在 catch 代碼塊最后团甲,語法如下:

```

try{

? // 程序代碼

}catch(異常類型1 異常的變量名1){

? // 程序代碼

}catch(異常類型2 異常的變量名2){

? // 程序代碼

}finally{

? // 程序代碼

}```

實例

```

ExcepTest.java 文件代碼:

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");

? ? }

? }

}

```

以上實例編譯運行結果如下:

```

Exception thrown? :java.lang.ArrayIndexOutOfBoundsException: 3

First element value: 6

The finally statement is executed

```

注意下面事項:

catch 不能獨立于 try 存在。

在 try/catch 后面添加 finally 塊并非強制性要求的黍聂。

try 代碼后不能既沒 catch 塊也沒 finally 塊躺苦。

try, catch, finally 塊之間不能添加任何代碼。

聲明自定義異常

在 Java 中你可以自定義異常产还。編寫自己的異常類時需要記住下面的幾點匹厘。

所有異常都必須是 Throwable 的子類。

如果希望寫一個檢查性異常類脐区,則需要繼承 Exception 類愈诚。

如果你想寫一個運行時異常類,那么需要繼承 RuntimeException 類牛隅。

可以像下面這樣定義自己的異常類:

```

class MyException extends Exception{

}

```

只繼承Exception 類來創(chuàng)建的異常類是檢查性異常類炕柔。

下面的 InsufficientFundsException 類是用戶定義的異常類,它繼承自 Exception媒佣。

一個異常類和其它任何類一樣匕累,包含有變量和方法。

實例

以下實例是一個銀行賬戶的模擬默伍,通過銀行卡的號碼完成識別欢嘿,可以進行存錢和取錢的操作授霸。

InsufficientFundsException.java 文件代碼:

```

// 文件名InsufficientFundsException.java

import java.io.*;

//自定義異常類,繼承Exception類

public class InsufficientFundsException extends Exception

{

? //此處的amount用來儲存當出現(xiàn)異常(取出錢多于余額時)所缺乏的錢

? private double amount;

? public InsufficientFundsException(double amount)

? {

? ? this.amount = amount;

? }

? public double getAmount()

? {

? ? return amount;

? }

}

```

為了展示如何使用我們自定義的異常類际插,

在下面的 CheckingAccount 類中包含一個 withdraw() 方法拋出一個 InsufficientFundsException 異常碘耳。

CheckingAccount.java 文件代碼:


// 文件名稱 CheckingAccount.java

import java.io.*;

//此類模擬銀行賬戶

public class CheckingAccount

{

? //balance為余額,number為卡號

? 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 程序示范了如何調用 CheckingAccount 類的 deposit() 和 withdraw() 方法框弛。

BankDemo.java 文件代碼:

```

//文件名稱 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();

? ? ? }

? ? }

}

```

編譯上面三個文件辛辨,并運行程序 BankDemo,得到結果如下所示:

```

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中定義了兩種類型的異常和錯誤瑟枫。


JVM(Java虛擬機) 異常:由 JVM 拋出的異扯犯悖或錯誤。例如:NullPointerException 類慷妙,ArrayIndexOutOfBoundsException 類僻焚,ClassCastException 類。

程序級異常:由程序或者API程序拋出的異常膝擂。例如 IllegalArgumentException 類虑啤,IllegalStateException 類。

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末架馋,一起剝皮案震驚了整個濱河市狞山,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌叉寂,老刑警劉巖萍启,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異屏鳍,居然都是意外死亡勘纯,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門钓瞭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來驳遵,“玉大人,你說我怎么就攤上這事降淮〕瘢” “怎么了搏讶?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵佳鳖,是天一觀的道長。 經(jīng)常有香客問我媒惕,道長系吩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任妒蔚,我火速辦了婚禮穿挨,結果婚禮上月弛,老公的妹妹穿的比我還像新娘。我一直安慰自己科盛,他們只是感情好帽衙,可當我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著贞绵,像睡著了一般厉萝。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上榨崩,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天谴垫,我揣著相機與錄音,去河邊找鬼母蛛。 笑死翩剪,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的彩郊。 我是一名探鬼主播前弯,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼秫逝!你這毒婦竟也來了博杖?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤筷登,失蹤者是張志新(化名)和其女友劉穎剃根,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體前方,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡狈醉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了惠险。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片苗傅。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖班巩,靈堂內(nèi)的尸體忽然破棺而出渣慕,到底是詐尸還是另有隱情,我是刑警寧澤抱慌,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布逊桦,位于F島的核電站,受9級特大地震影響抑进,放射性物質發(fā)生泄漏强经。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一寺渗、第九天 我趴在偏房一處隱蔽的房頂上張望匿情。 院中可真熱鬧兰迫,春花似錦、人聲如沸炬称。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽玲躯。三九已至须鼎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間府蔗,已是汗流浹背晋控。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留姓赤,地道東北人赡译。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像不铆,于是被迫代替她去往敵國和親蝌焚。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 異常是程序中的一些錯誤誓斥,但并不是所有的錯誤都是異常只洒,并且錯誤有時候是可以避免的。 比如說劳坑,你的代碼少了一個分號毕谴,那...
    代碼人生sl閱讀 337評論 0 0
  • 主要兩類異常: 檢查性異常:也就是我們經(jīng)常遇到的IO異常,以及SQL異常都是這種異常距芬。對于這種異常涝开,JAVA編譯器...
    啊玄吶閱讀 182評論 0 0
  • 當當當當當當,各位看官框仔,好久不見舀武,甚是想念。 今天我們來聊聊Java里的一個小妖精离斩,那就是異常银舱。 什么是異常?什么...
    Python編程社區(qū)閱讀 334評論 0 0
  • 這篇文章主要是對Java異常選擇和使用中的一些誤區(qū)的總結和歸納跛梗,希望各位讀者能夠熟練掌握異常處理的一些注意點和原則...
    唐老鴨z閱讀 417評論 0 0
  • 異常是程序中的一些錯誤茄袖,但并不是所有的錯誤都是異常操软,并且錯誤有時候是可以避免的嘁锯。 比如說宪祥,你的代碼少了一個分號聂薪,那...
    耳東陳_f1e5閱讀 295評論 0 4