異常黍匾,斷言和日志

編寫程序的時候總會遇到這樣那樣的錯誤赔嚎,為了盡量避免錯誤或者外部環(huán)境造成的數(shù)據(jù)丟失等情況,Java中至少應(yīng)該做到以下幾點:

·向用戶通知錯誤

·保存所有的工作

·允許用戶妥善的退出程序

因此就有了異常處理问麸、斷言和日志這些機制。

異常處理

如果由于出現(xiàn)錯誤而使得操作沒有完成钞翔,程序應(yīng)該:

·返回到一種安全狀態(tài),并能夠讓用戶執(zhí)行其他的命令

·或者允許用戶保存所有工作的結(jié)果席舍,并以妥善的方式種植程序

困難點在于檢測(甚至引發(fā))錯誤條件的代碼通常與那些能夠讓數(shù)據(jù)恢復(fù)到安全狀態(tài)或者能夠保存用戶工作并妥善退出的代碼相聚很遠(yuǎn)布轿。

異常處理的任務(wù)就是將控制權(quán)從產(chǎn)生錯誤的地方轉(zhuǎn)移到能夠處理這種情況的錯誤處理器。

需要考慮以下這些錯誤:

·用戶輸入錯誤? ? 包括鍵盤輸入錯誤来颤,還有一些語法錯誤

·設(shè)備錯誤? ? ? ? ? ? 硬件出現(xiàn)問題

·物理限制? ? ? ? ? ? 磁盤已滿

·代碼錯誤? ? ? ? ? ? 程序方法可能沒有正確的完成工作

在Java中汰扭,如果某個方法不能夠采用正常的途經(jīng)完成它的任務(wù),就會從另一個途徑推出方法福铅,這種情況下萝毛,方法不會返回任何值,而是拋出(throw)一個封裝了錯誤信息的對象滑黔。

這個方法會立刻推出笆包,而且也不會從調(diào)用這個方法的程序代碼繼續(xù)執(zhí)行,而是異常處理機制開始搜索能夠處理這種異常狀況的異常處理器略荡。

異常有自己的語法和特定的繼承層次結(jié)構(gòu)庵佣。

異常分類

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

異常對象都是派生Trowable類的一個類實例。

有兩個分支汛兜,Error和Exception巴粪。其中Error類層次結(jié)構(gòu)描述了Java運行時系統(tǒng)的內(nèi)部錯誤和資源耗盡錯誤,這種情況很少發(fā)生,但是發(fā)生了就沒辦法肛根。

重點關(guān)注Exception層次結(jié)構(gòu)辫塌,它又分解為兩個分支:一個派生于RuntimeException,另一個是其他異常派哲。

RuntimeException包括:

·錯誤的強制類型轉(zhuǎn)換

·數(shù)組訪問越界

·訪問null指針

不屬于的包括:

·視圖超越文件末尾繼續(xù)讀取數(shù)據(jù)

·試圖打開一個不存在的文件

·視圖根據(jù)給定的字符串查找Class對象臼氨,而這個字符串表示的類并不存在。

“如果出現(xiàn)RuntimeException異常狮辽,那么就一定是你的問題一也。”

非檢查型異常(unchecked):Error類和RuntimeException類派生的異常

檢查型異常:其他異常

編譯器要求為所有檢查型異常提供異常處理器

聲明檢查型異常

遇到下面四種情況時會拋出異常:

·調(diào)用了一個拋出檢查型異常的方法

·檢測到一個錯誤喉脖,并利用throw語句拋出一個檢查型異常

·程序出現(xiàn)錯誤

·Java虛擬機或運行時庫出現(xiàn)內(nèi)部錯誤

為什么要聲明檢查型異常椰苟。例如FileInputStream方法,并不能保證在執(zhí)行這個方法的時候树叽,外部文件沒有被刪除或者更改舆蝴。也就是程序內(nèi)部不能保證的情況,就需要聲明檢查型異常题诵,否則一旦出錯洁仗,所有線程都會終止。

為什么不用聲明非檢查型異常性锭。如果出現(xiàn)Error類赠潦,那么在你的控制之外,無法關(guān)注草冈。如果是RuntimeError她奥,編輯器會自動拋出異常,而且更應(yīng)該關(guān)注如何將這個錯誤避免怎棱,而不是聲明異常哩俭。

如何拋出異常

如下

String readData(Scanner in) throws EOFException{

? ? ...

? ? while(...){

? ????? if ( !in.hasNext()){

? ? ? ? if (n < len)? ? throw new EOFException;

? ? ?????}

? ? }

? ? return s;

}

·找到一個合適的異常類

·創(chuàng)建這個類的一個對象

·將對象拋出

創(chuàng)建異常類

自定義的類應(yīng)該包括兩個構(gòu)造器,一個是默認(rèn)的構(gòu)造器拳恋,另一個是包含詳細(xì)描述信息的構(gòu)造器凡资。例如

class FileFormatException extends IOException{

????public FileFormatException(){}

? ? public? FileFormatException(String gripe){ super(gripe); }

}

然后像上面一樣拋出就可以


捕獲異常

try/catch語句

加入程序拋出了一個異常但是沒有捕獲,那么就會終止程序谬运,然后在控制臺上打印出異常信息隙赁。

使用try/catch語句可以捕獲異常,如果在try語句中拋出了IOException異常梆暖,catch就會捕獲并執(zhí)行catch中的代碼

注意執(zhí)行順序鸳谜,是先執(zhí)行try中的代碼,直到拋出異常式廷,然后跳過剩下的代碼咐扭,去執(zhí)行catch中的代碼。

public?static?void?read(String?filename){

????try?{

????????var?in?=?new?FileInputStream(file);

????????int?b;

????}?catch?(IOException?e)?{

????????e.printStackTrace();

????}

}

注意,這里沒有使用

public static void read(String filename) throws IOException{}

兩者的區(qū)別在于蝗肪,throws給整個方法拋出一個異常袜爪,也就是說,調(diào)用這個方法時可能會拋出這個異常薛闪。這是傳遞異常辛馆。

而try/catch在程序內(nèi)部就解決了異常,調(diào)用這個方法并不會拋出異常豁延。這是處理異常昙篙。

如果拋出了異常,要么傳遞異常要么處理異常诱咏。否則程序就會終止苔可。

捕獲多個異常

try{...}

catch(FileNotFoundException e){...}

catch(UnkonwnHostException e){...}

catch(IOException e){...}

也可以合并

catch(FileNotFoundException | UnkonwnHostException e){...}

再次拋出異常與異常鏈

·如果想改變異常的類型,就可以再次拋出異常

try{...}

catch{SQLException e}{

????throw new ServletException();

}

·或者一個方法不允許拋出檢查型異常但是卻發(fā)生了袋狞,也可以使用這種技術(shù)焚辅。

·或者在拋出異常之前,想要記錄這個異常再拋出苟鸯。

finally子句

try{...}

catch(Exception e){...}

finally{...}

有好幾種情況:try中出現(xiàn)異常同蜻,catch中出現(xiàn)異常,異常有沒有被捕獲等等早处。但是不管如何湾蔓,finally子句中的代碼最后都會執(zhí)行。

try-with-Resources語句

假如要打開的資源屬于一個實現(xiàn)了AutoCloseable接口的類砌梆,就可以用這個語句

try(Resource res = ...){

? ? do something

}

無論有沒有異常默责,最后都會執(zhí)行res.close(),等同于finally么库。

try(var in = new Scanner(new FileInputStream("/usr/share/dict/words"), StandardCharset.UTF_8))

{

? ? while (in.hasNext())

? ? ? ? out.println(in.next());

}

分析堆棧軌跡(stack trace)元素

當(dāng)Java程序因為一個未捕獲的異常而終止時,就會顯示堆棧軌跡甘有。

詳情看《Java核心技術(shù)·卷一》P295頁程序诉儒。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市亏掀,隨后出現(xiàn)的幾起案子忱反,更是在濱河造成了極大的恐慌,老刑警劉巖滤愕,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件温算,死亡現(xiàn)場離奇詭異,居然都是意外死亡间影,警方通過查閱死者的電腦和手機注竿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人巩割,你說我怎么就攤上這事裙顽。” “怎么了宣谈?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵愈犹,是天一觀的道長。 經(jīng)常有香客問我闻丑,道長漩怎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任嗦嗡,我火速辦了婚禮勋锤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘酸钦。我一直安慰自己怪得,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布卑硫。 她就那樣靜靜地躺著徒恋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪欢伏。 梳的紋絲不亂的頭發(fā)上入挣,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天,我揣著相機與錄音硝拧,去河邊找鬼径筏。 笑死,一個胖子當(dāng)著我的面吹牛障陶,可吹牛的內(nèi)容都是我干的滋恬。 我是一名探鬼主播,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼抱究,長吁一口氣:“原來是場噩夢啊……” “哼恢氯!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起鼓寺,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤勋拟,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后妈候,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體敢靡,經(jīng)...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年苦银,在試婚紗的時候發(fā)現(xiàn)自己被綠了啸胧。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赶站。...
    茶點故事閱讀 40,865評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖吓揪,靈堂內(nèi)的尸體忽然破棺而出亲怠,到底是詐尸還是另有隱情,我是刑警寧澤柠辞,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布团秽,位于F島的核電站,受9級特大地震影響叭首,放射性物質(zhì)發(fā)生泄漏习勤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一焙格、第九天 我趴在偏房一處隱蔽的房頂上張望图毕。 院中可真熱鬧,春花似錦眷唉、人聲如沸予颤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蛤虐。三九已至,卻和暖如春肝陪,著一層夾襖步出監(jiān)牢的瞬間驳庭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工氯窍, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留饲常,地道東北人。 一個月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓狼讨,卻偏偏與公主長得像贝淤,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子政供,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,870評論 2 361