最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

Java二十四篇:異常

2023-03-06 00:19 作者:小劉Java之路  | 我要投稿

異常的概念

異常是程序中的一些錯(cuò)誤,但并不是所有的錯(cuò)誤都是異常,并且錯(cuò)誤有時(shí)候是可以避免的。

比如說,你的代碼少了一個(gè)分號(hào),那么運(yùn)行出來結(jié)果是提示是錯(cuò)誤java.lang.Error;如果你用System.out.println(11/0),那么你是因?yàn)槟阌?做了除數(shù),會(huì)拋出java.lang.ArithmeticException的異常。

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

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

  • 要打開的文件不存在。

  • 網(wǎng)絡(luò)通信時(shí)連接中斷,或者JVM內(nèi)存溢出。

這些異常有的是因?yàn)橛脩翦e(cuò)誤引起,有的是程序錯(cuò)誤引起的,還有其它一些是因?yàn)槲锢礤e(cuò)誤引起的。

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

  • 檢查性異常:最具代表的檢查性異常是用戶錯(cuò)誤或問題引起的異常,這是程序員無法預(yù)見的。例如要打開一個(gè)不存在文件時(shí),一個(gè)異常就發(fā)生了,這些異常在編譯時(shí)不能被簡單地忽略。

  • 運(yùn)行時(shí)異常:運(yùn)行時(shí)異常是可能被程序員避免的異常。與檢查性異常相反,運(yùn)行時(shí)異??梢栽诰幾g時(shí)被忽略。

  • 錯(cuò)誤:錯(cuò)誤不是異常,而是脫離程序員控制的問題。錯(cuò)誤在代碼中通常被忽略。例如,當(dāng)棧溢出時(shí),一個(gè)錯(cuò)誤就發(fā)生了,它們?cè)诰幾g也檢查不到的。

異常指不期而至的各種狀況,如:文件找不到、網(wǎng)絡(luò)連接失敗、除0操作、非法參數(shù)等。異常是一個(gè)事件,它發(fā)生在程序運(yùn)行期間,干擾了正常的指令流程。

Java語言在設(shè)計(jì)的當(dāng)初就考慮到這些問題,提出異常處理的框架的方案,所有的異常都可以用一個(gè)異常類來表示,不同類型的異常對(duì)應(yīng)不同的子類異常(目前我們所說的異常包括錯(cuò)誤概念),定義異常處理的規(guī)范,在JDK1.4版本以后增加了異常鏈機(jī)制,從而便于跟蹤異常。

Java異常是一個(gè)描述在代碼段中發(fā)生異常的對(duì)象,當(dāng)發(fā)生異常情況時(shí),一個(gè)代表該異常的對(duì)象被創(chuàng)建并且在導(dǎo)致該異常的方法中被拋出,而該方法可以選擇自己處理異?;蛘邆鬟f該異常。

異常的體系結(jié)構(gòu)

Java把異常當(dāng)作對(duì)象來處理,并定義一個(gè)基類java.lang.Throwable作為所有異常的超類。

在Java API中已經(jīng)定義了許多異常類,這些異常類分為兩大類,錯(cuò)誤Error和異常Exception。

Java異常層次結(jié)構(gòu)圖如下圖所示:

img

從圖中可以看出所有異常類型都是內(nèi)置類Throwable的子類,因而Throwable在異常類的層次結(jié)構(gòu)的頂層。

接下來Throwable分成了兩個(gè)不同的分支,一個(gè)分支是Error,它表示不希望被程序捕獲或者是程序無法處理的錯(cuò)誤。另一個(gè)分支是Exception,它表示用戶程序可能捕捉的異常情況或者說是程序可以處理的異常。其中異常類Exception又分為運(yùn)行時(shí)異常(RuntimeException)和非運(yùn)行時(shí)異常。

Java異常又可以分為不受檢查異常(Unchecked Exception)和檢查異常(Checked Exception)。

下面將詳細(xì)講述這些異常之間的區(qū)別與聯(lián)系:

  • Error:Error類對(duì)象由 Java 虛擬機(jī)生成并拋出,大多數(shù)錯(cuò)誤與代碼編寫者所執(zhí)行的操作無關(guān)。例如,Java虛擬機(jī)運(yùn)行錯(cuò)誤(Virtual MachineError),當(dāng)JVM不再有繼續(xù)執(zhí)行操作所需的內(nèi)存資源時(shí),將出現(xiàn) OutOfMemoryError。這些異常發(fā)生時(shí),Java虛擬機(jī)(JVM)一般會(huì)選擇線程終止;還有發(fā)生在虛擬機(jī)試圖執(zhí)行應(yīng)用時(shí),如類定義錯(cuò)誤(NoClassDefFoundError)、鏈接錯(cuò)誤(LinkageError)。這些錯(cuò)誤是不可查的,因?yàn)樗鼈冊(cè)趹?yīng)用程序的控制和處理能力之 外,而且絕大多數(shù)是程序運(yùn)行時(shí)不允許出現(xiàn)的狀況。對(duì)于設(shè)計(jì)合理的應(yīng)用程序來說,即使確實(shí)發(fā)生了錯(cuò)誤,本質(zhì)上也不應(yīng)該試圖去處理它所引起的異常狀況。在Java中,錯(cuò)誤通常是使用Error的子類描述。

  • Exception:在Exception分支中有一個(gè)重要的子類RuntimeException(運(yùn)行時(shí)異常),該類型的異常自動(dòng)為你所編寫的程序定義ArrayIndexOutOfBoundsException(數(shù)組下標(biāo)越界)、NullPointerException(空指針異常)、ArithmeticException(算術(shù)異常)、MissingResourceException(丟失資源)、ClassNotFoundException(找不到類)等異常,這些異常是不檢查異常,程序中可以選擇捕獲處理,也可以不處理。這些異常一般是由程序邏輯錯(cuò)誤引起的,程序應(yīng)該從邏輯角度盡可能避免這類異常的發(fā)生;而RuntimeException之外的異常我們統(tǒng)稱為非運(yùn)行時(shí)異常,類型上屬于Exception類及其子類,從程序語法角度講是必須進(jìn)行處理的異常,如果不處理,程序就不能編譯通過。如IOException、SQLException等以及用戶自定義的Exception異常,一般情況下不自定義檢查異常。

注意

Error和Exception的區(qū)別:Error通常是災(zāi)難性的致命的錯(cuò)誤,是程序無法控制和處理的,當(dāng)出現(xiàn)這些異常時(shí),Java虛擬機(jī)(JVM)一般會(huì)選擇終止線程;Exception通常情況下是可以被程序處理的,并且在程序中應(yīng)該盡可能的去處理這些異常。

Java異常的處理機(jī)制

Java的異常處理本質(zhì)上是拋出異常和捕獲異常。

  • 拋出異常:要理解拋出異常,首先要明白什么是異常情形(exception condition),它是指阻止當(dāng)前方法或作用域繼續(xù)執(zhí)行的問題。其次把異常情形和普通問題相區(qū)分,普通問題是指在當(dāng)前環(huán)境下能得到足夠的信息,總能處理這個(gè)錯(cuò)誤。對(duì)于異常情形,已經(jīng)無法繼續(xù)下去了,因?yàn)樵诋?dāng)前環(huán)境下無法獲得必要的信息來解決問題,你所能做的就是從當(dāng)前環(huán)境中跳出,并把問題提交給上一級(jí)環(huán)境,這就是拋出異常時(shí)所發(fā)生的事情。拋出異常后,會(huì)有幾件事隨之發(fā)生。首先,是像創(chuàng)建普通的java對(duì)象一樣將使用new在堆上創(chuàng)建一個(gè)異常對(duì)象;然后,當(dāng)前的執(zhí)行路徑(已經(jīng)無法繼續(xù)下去了)被終止,并且從當(dāng)前環(huán)境中彈出對(duì)異常對(duì)象的引用。此時(shí),異常處理機(jī)制接管程序,并開始尋找一個(gè)恰當(dāng)?shù)牡胤嚼^續(xù)執(zhí)行程序,這個(gè)恰當(dāng)?shù)牡胤骄褪钱惓L幚沓绦蚧蛘弋惓L幚砥?,它的任?wù)是將程序從錯(cuò)誤狀態(tài)中恢復(fù),以使程序要么換一種方式運(yùn)行,要么繼續(xù)運(yùn)行下去。

舉個(gè)簡單的例子,假使我們創(chuàng)建了一個(gè)學(xué)生對(duì)象Student的一個(gè)引用stu,在調(diào)用的時(shí)候可能還沒有初始化。所以在使用這個(gè)對(duì)象引用調(diào)用其他方法之前,要先對(duì)它進(jìn)行檢查,可以創(chuàng)建一個(gè)代表錯(cuò)誤信息的對(duì)象,并且將它從當(dāng)前環(huán)境中拋出,這樣就把錯(cuò)誤信息傳播到更大的環(huán)境中。

if(stu == null){
? ?thrownew NullPointerException();
}

這就拋出了異常,它將在其他的地方得到執(zhí)行或者處理,具體是哪個(gè)地方后面將很快介紹,代碼中出現(xiàn)的 throw 是一個(gè)關(guān)鍵字,暫時(shí)先不做過多講解,后面會(huì)詳細(xì)講解。

  • 捕獲異常:在方法拋出異常之后,運(yùn)行時(shí)系統(tǒng)將轉(zhuǎn)為尋找合適的異常處理器(exception handler)。潛在的異常處理器是異常發(fā)生時(shí)依次存留在調(diào)用棧中的方法的集合。當(dāng)異常處理器所能處理的異常類型與方法拋出的異常類型相符時(shí),即為合適的異常處理器。運(yùn)行時(shí)系統(tǒng)從發(fā)生異常的方法開始,依次回查調(diào)用棧中的方法,直至找到含有合適異常處理器的方法并執(zhí)行。當(dāng)運(yùn)行時(shí)系統(tǒng)遍歷調(diào)用棧而未找到合適的異常處理器,則運(yùn)行時(shí)系統(tǒng)終止。同時(shí),意味著Java程序的終止。

提示

對(duì)于運(yùn)行時(shí)異常、錯(cuò)誤和檢查異常,Java技術(shù)所要求的異常處理方式有所不同。

由于運(yùn)行時(shí)異常及其子類的不可查性,為了更合理、更容易地實(shí)現(xiàn)應(yīng)用程序,Java規(guī)定,運(yùn)行時(shí)異常將由Java運(yùn)行時(shí)系統(tǒng)自動(dòng)拋出,允許應(yīng)用程序忽略運(yùn)行時(shí)異常

對(duì)于方法運(yùn)行中可能出現(xiàn)的Error,當(dāng)運(yùn)行方法不欲捕捉時(shí),Java允許該方法不做任何拋出聲明。因?yàn)?,大多?shù)Error異常屬于永遠(yuǎn)不能被允許發(fā)生的狀況,也屬于合理的應(yīng)用程序不該捕捉的異常。

對(duì)于所有的檢查異常,Java規(guī)定:一個(gè)方法必須捕捉,或者聲明拋出方法之外。也就是說,當(dāng)一個(gè)方法選擇不捕捉檢查異常時(shí),它必須聲明將拋出異常。

Java異常處理涉及到五個(gè)關(guān)鍵字,分別是:try、catch、finally、throw、throws。下面將驟一介紹,通過認(rèn)識(shí)這五個(gè)關(guān)鍵字,掌握基本異常處理知識(shí)。

??try?? ? ? ?-- 用于監(jiān)聽。將要被監(jiān)聽的代碼(可能拋出異常的代碼)放在try語句塊之內(nèi),當(dāng)try語句塊內(nèi)發(fā)生異常時(shí),異常就被拋出。??catch?? -- 用于捕獲異常。catch用來捕獲try語句塊中發(fā)生的異常。??finally??-- finally語句塊總是會(huì)被執(zhí)行。它主要用于回收在try塊里打開的物力資源(如數(shù)據(jù)庫連接、網(wǎng)絡(luò)連接和磁盤文件)。只有finally塊,執(zhí)行完成之后,才會(huì)回來執(zhí)行try或者catch塊中的return或者throw語句,如果finally中使用了return或者throw等終止方法的語句,則就不會(huì)跳回執(zhí)行,直接停止。??throw?? -- 用于拋出異常。??throws?-- 用在方法簽名中,用于聲明該方法可能拋出的異常。

異常處理的基本語法

1、try-catch


?try{ ? ? ?//程序代碼 ?}catch (ExceptionName e1){ ? ? ?//Catch塊 ?}

2、throw


//演示throw ?public class Demo4 { ? ? ?public static void main(String[] args) { ? ? ? ? ?test(); ? ? ?} ? ? ?public static void test() { ? ? ? ? ?int a = 520; ? ? ? ? ?int b = 0; ? ? ? ? ?if (b == 0) { ? ? ? ? ? ? ?throw new ArithmeticException(); ? ? ? ? ?} else { ? ? ? ? ? ? ?System.out.println(a / b); ? ? ? ? ?} ? ? ?} ?}

3、throws

?//演示throws ?public class Demo4 { ? ? ?public static void main(String[] args) { ? ? ? ? ?try { ? ? ? ? ? ? ?test(); ? ? ? ? ?} catch (Exception e) { ? ? ? ? ? ? ?e.printStackTrace(); ? ? ? ? ?} ? ? ?} ? ? ?public static void test() throws Exception { ? ? ? ? ?int a = 520; ? ? ? ? ?int b = 0; ? ? ? ? ?if (b == 0) { ? ? ? ? ? ? ?throw new Exception(); ? ? ? ? ?} else { ? ? ? ? ? ? ?System.out.println(a / b); ? ? ? ? ?} ? ? ?} ?}

4、finally

public class Demo2 { ? ? ?public static void main(String[] args) { ? ? ? ? ?System.out.println(test()); ? ? ?} ? ? ?public static String test(){ ? ? ? ? ?int[] array = new int[2]; ? ? ? ? ?try{ ? ? ? ? ? ? ?array[3] = 0; ? ? ? ? ? ? ?return "This is try"; ? ? ? ? ?}catch (ArrayIndexOutOfBoundsException e){ ? ? ? ? ? ? ?System.out.println(e); ? ? ? ? ? ? ?return "This is catch 1"; ? ? ? ? ?}catch (Exception e){ ? ? ? ? ? ? ?System.out.println(e); ? ? ? ? ? ? ?return "This is catch 2"; ? ? ? ? ?}finally { ? ? ? ? ? ? ?System.out.println("This is finally"); ? ? ? ? ? ? ?//return "This is finally's return"; ? ? ? ? ?} ? ? ?} ?}

面試題:

throws和throw的區(qū)別

A:throws

  • 用在方法聲明后,跟的是異常類名

  • 可以跟多個(gè)異常類名,用逗號(hào)隔開

  • 表示拋出異常,由該方法的調(diào)用者來處理

  • throws表示出現(xiàn)異常的一種可能性,不一定會(huì)發(fā)生這些異常

B:throw

  • 用在方法體內(nèi),跟的是異常對(duì)象名

  • 只能拋出一個(gè)異常對(duì)象名

  • 表示拋出異常,由方法體內(nèi)的語句處理

  • 執(zhí)行throw則一定拋出了某種異常

異常鏈

異常鏈顧名思義就是將異常發(fā)生的原因一個(gè)傳一個(gè)串起來,即把底層的異常信息傳給上層,這樣逐層拋出。Java API文檔中給出了一個(gè)簡單的模型:

try { ?
? ?lowLevelOp(); ?
} catch (LowLevelException le) { ?
? ?throw (HighLevelException) new HighLevelException().initCause(le); ?
}

當(dāng)程序捕獲到了一個(gè)底層異常,在處理部分選擇了繼續(xù)拋出一個(gè)更高級(jí)別的新異常給此方法的調(diào)用者。這樣異常的原因就會(huì)逐層傳遞。這樣,位于高層的異常遞歸調(diào)用getCause()方法,就可以遍歷各層的異常原因。這就是Java異常鏈的原理。異常鏈的實(shí)際應(yīng)用很少,發(fā)生異常時(shí)候逐層上拋不是個(gè)好注意, 上層拿到這些異常又能奈之何?而且異常逐層上拋會(huì)消耗大量資源, 因?yàn)橐4嬉粋€(gè)完整的異常鏈信息.

自定義異常

使用Java內(nèi)置的異常類可以描述在編程時(shí)出現(xiàn)的大部分異常情況。除此之外,用戶還可以自定義異常。用戶自定義異常類,只需繼承Exception類即可。

在程序中使用自定義異常類,大體可分為以下幾個(gè)步驟:

  • 創(chuàng)建自定義異常類。

  • 在方法中通過throw關(guān)鍵字拋出異常對(duì)象。

  • 如果在當(dāng)前拋出異常的方法中處理異常,可以使用try-catch語句捕獲并處理;否則在方法的聲明處通過throws關(guān)鍵字指明要拋出給方法調(diào)用者的異常,繼續(xù)進(jìn)行下一步操作。

  • 在出現(xiàn)異常方法的調(diào)用者中捕獲并處理異常。

總結(jié):

img
img


常見的異常:

異常類型說明Exception異常層次結(jié)構(gòu)的根類RuntimeException運(yùn)行時(shí)異常,多數(shù) java.lang 異常的根類ArithmeticException算術(shù)譜誤異常,如以零做除數(shù)ArraylndexOutOfBoundException數(shù)組大小小于或大于實(shí)際的數(shù)組大小NullPointerException嘗試訪問 null 對(duì)象成員,空指針異常ClassNotFoundException不能加載所需的類NumberF ormatException數(shù)字轉(zhuǎn)化格式異常,比如字符串到 float 型數(shù)字的轉(zhuǎn)換無效IOExceptionI/O 異常的根類F ileN otF oundException找不到文件EOFException文件結(jié)束InterruptedException線程中斷IllegalArgumentException方法接收到非法參數(shù)ClassCastException類型轉(zhuǎn)換異常SQLException操作數(shù)據(jù)庫異常




Java二十四篇:異常的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國家法律
陵水| 嘉黎县| 河津市| 太康县| 临潭县| 盐津县| 永福县| 鹤峰县| 娱乐| 鹤山市| 屏东市| 札达县| 长葛市| 昔阳县| 若尔盖县| 开原市| 琼海市| 赣榆县| 丽水市| 昌都县| 巢湖市| 墨竹工卡县| 化州市| 安宁市| 龙江县| 犍为县| 盖州市| 望谟县| 霸州市| 宁津县| 台江县| 朝阳区| 无锡市| 新安县| 高陵县| 兴和县| 南昌市| 桐柏县| 洪雅县| 腾冲县| 宁蒗|