国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > Java > 正文

Java基礎(chǔ)(十)異常處理

2019-11-06 07:24:19
字體:
供稿:網(wǎng)友

java基礎(chǔ)(十) 異常處理

異常的處理流程;自定義異常;斷言;

異常:我們的生活中,經(jīng)常會(huì)遇到異常現(xiàn)象。比如我們?cè)谏习嗟穆飞希瑫?huì)遇到很多情況。我們的目標(biāo)是:住處—>公司。但是你在上班的路上,會(huì)遇到各類的異常情況。比如:天氣災(zāi)難(臺(tái)風(fēng)等)、地鐵堵的你進(jìn)不去、地鐵發(fā)生事故。在我們的編程時(shí)也是如此,程序在運(yùn)行的時(shí)候也會(huì)遇到各種各樣的異常。

為了解決異常會(huì)產(chǎn)生的各種不良后果,我們可以有如下2種做法:

避免出現(xiàn)異常。代碼內(nèi)保證,比如調(diào)用實(shí)例的.set()方法前,先進(jìn)行判斷實(shí)例是否為空。即if(實(shí)例!=null){}處理異常。在程序編寫的過程中,考慮可能出現(xiàn)的異常類型,捕獲異常并處理異常,保證程序的魯棒性。

Java提供了一套完整的異常處理機(jī)制。正確使用這套機(jī)制,可以大大提高代碼的健壯性。所謂程序的健壯性,指程序在多數(shù)情況下能夠正常運(yùn)行,返回預(yù)期的結(jié)果;如果遇到異常情況,程序可以采取周到的解決措施。

Java代碼通過面向?qū)ο蟮乃枷雭硖幚懋惓#沟么a具有更好的可維護(hù)性。Java的異常處理機(jī)制主要有如下幾點(diǎn)的優(yōu)點(diǎn):

把不同類型的異常進(jìn)行分類,用Java類表示異常,這種類被稱為異常類。把異常情況表示為異常類,可以充分發(fā)揮類的可擴(kuò)展和重用的優(yōu)勢(shì)。異常的流程代碼可以和業(yè)務(wù)代碼進(jìn)行分離,提高了程序的可重用性,簡(jiǎn)化了程序的結(jié)構(gòu)。可以靈活的處理異常。即可以處理異常;也可以不處理異常,僅將異常拋出,由異常的上一級(jí)或者調(diào)用著進(jìn)行處理。

1. 異常的基本概念

異常的產(chǎn)生條件 整數(shù)相除計(jì)算中,除數(shù)為0;通過一個(gè)沒有指向任何具體對(duì)象的引用去調(diào)用 實(shí)例對(duì)象的方法(NullPointer異常);通過數(shù)據(jù)的長(zhǎng)度作為下標(biāo)訪問數(shù)組元素(OutOfBoundarys 數(shù)組越界);將一個(gè)引用強(qiáng)制準(zhǔn)換位不想干的對(duì)象。(如 Integer類型 強(qiáng)制轉(zhuǎn)換為 ArrayList類型)異常會(huì)改變程序正常的處理流程;異常產(chǎn)生后,程序的正常處理流程被打破,要不程序終止,要不程序會(huì)跳轉(zhuǎn)到異常處理模塊。當(dāng)一個(gè)異常出現(xiàn)后,異常會(huì)被Java虛擬機(jī)封裝成異常對(duì)象拋出。用來處理異常的代碼被稱為異常處理器。通過異常處理器來捕捉異常。package com.us.demo.exception;public class ExceptionTest { public static int divide(int firstNumber, int secondNumber){ int result = 0; try{ result = firstNumber / secondNumber; }catch(ArithmeticException ex){ System.out.2. 異常的基本語(yǔ)句

2.1 try…catch 語(yǔ)句

在Java語(yǔ)言內(nèi),常用try...catch語(yǔ)句來處理異常。具體格式如下所示:

try{// 可能會(huì)出現(xiàn)異常的代碼}catch(異常類型 異常參數(shù)){// 異常處理代碼}catch(異常類型 異常參數(shù)){// 異常處理代碼}如果try代碼塊內(nèi)的代碼沒有拋出異常,try代碼塊會(huì)被順序執(zhí)行完,catch代碼塊的程序不會(huì)被執(zhí)行;如果try代碼塊內(nèi)的代碼拋出catch處聲明的異常類型,程序會(huì)跳過try代碼塊,直接執(zhí)行catch代碼塊的內(nèi)容; 可以存在多個(gè)catch代碼塊,具體執(zhí)行某一個(gè)。需要看try代碼塊內(nèi)拋出的異常類型決定。同一個(gè)異常類型只能被一個(gè)異常處理器處理。不能聲明2個(gè)異常處理器去處理同類異常。多個(gè)catch語(yǔ)句處理的異常類型不能越來越小。因?yàn)榇蟠螽惓n愋蜁?huì)被優(yōu)先捕獲,這樣后面的異常將永遠(yuǎn)不會(huì)生效。不能捕獲一個(gè)try代碼塊內(nèi)不會(huì)拋出的異常類型。如果try代碼塊內(nèi)拋出的異常類型,是catch代碼塊內(nèi)未聲明的異常類型,異常會(huì)被拋給調(diào)用者;那個(gè)調(diào)用了這段語(yǔ)句,誰(shuí)就應(yīng)當(dāng)處理這段異常代碼。

2.2 finally 語(yǔ)句(任何情況下都會(huì)被執(zhí)行的代碼)

由于異常會(huì)強(qiáng)制中斷正常流程,這會(huì)使得某些不管在任何情況下都必須執(zhí)行的步驟被忽略,從而影響程序的健壯性。

例如小王開了一家小店,在店里上班的正常流程為:打開店門、工作8個(gè)小時(shí)、關(guān)門。異常流程為:小王在工作時(shí)突然犯病,因而提前下班。例:

public void work() { try { 開門(); 工作8個(gè)小時(shí)(); 關(guān)門(); } catch(Exception e) { //去醫(yī)院 } }

假如小王在工作時(shí)突然犯病,那么流程會(huì)跳轉(zhuǎn)到catch代碼塊,這意味著關(guān)門的操作不會(huì)被執(zhí)行,這樣的流程顯然是不安全的,必須確保關(guān)門的操作在任何情況下都會(huì)被執(zhí)行。finally代碼塊能保證特定的操作總是會(huì)被執(zhí)行,它的形式如下:

public void work() { try { 開門(); 工作8個(gè)小時(shí)(); } catch(Exception e) { //去醫(yī)院 return; } finally { 關(guān)門(); } }

當(dāng)然finally代碼塊中代碼也可位于catch語(yǔ)句塊之后,例如:

public void work() { try { 開門(); 工作8個(gè)小時(shí)(); } catch(Exception e) { //去醫(yī)院 } 關(guān)門();}

這在某些情況下是可行的,但是不推薦,這樣。因?yàn)?

把try代碼的部分分離了開來,這樣使得程序松散,可讀性較差;影響程序的健壯性,例如catch部分繼續(xù)有異常拋出,那么關(guān)門的動(dòng)作就不會(huì)被執(zhí)行。

3. 異常的其他信息

3.1 異常的調(diào)用棧

異常的處理過程中,所經(jīng)歷的一系列的方法的調(diào)用過程,被稱為異常的調(diào)用棧。

異常的傳播(哪個(gè)調(diào)用,哪個(gè)處理) 異常發(fā)生后,異常所在的方法可以處理;異常所在的方法沒用處理,異常會(huì)被拋送給方法調(diào)用著,調(diào)用者可以處理;如果調(diào)用者沒用處理,異常將會(huì)進(jìn)一步拋出;如果異常一直沒用被處理,那么異常將會(huì)被拋送給Java虛擬機(jī),這將會(huì)導(dǎo)致程序的中斷。 如果異常沒有被捕獲,那么異常將會(huì)使你的程序停止運(yùn)行。 異常產(chǎn)生后,如果異常一直沒用被捕獲。那么該異常將會(huì)被拋Java虛擬機(jī)。程序?qū)⒈唤K止。經(jīng)常會(huì)使用的異常API getMessage(): 獲得具體的異常信息,可能為null;printStatckTrace:打印異常在傳播過程中所經(jīng)歷的一系列方法的信息,簡(jiǎn)稱為異常處理方法調(diào)用棧信息;在程序調(diào)試階段,此方法可用于追蹤錯(cuò)誤信息。

3.2 異常的層級(jí)關(guān)系

所有異常類的祖先為java.lang.Throwable類。它有2個(gè)直接的子類:

3.2.1 Error類

表示僅靠程序無(wú)法恢復(fù)的嚴(yán)重錯(cuò)誤,比如內(nèi)存空間不足,或者Java虛擬機(jī)調(diào)用方法棧溢出。在多數(shù)情況下,調(diào)用此方法,程序建議立即中止。

3.2.1 Exception類

表示程序可以處理的異常,這類異常主要分為2種:運(yùn)行時(shí)異常和受檢查異常。

運(yùn)行時(shí)異常

基本概念

RuntimeException及其子類被稱為運(yùn)行時(shí)異常,這種異常的特點(diǎn)是編譯器不會(huì)去檢查它們。也就是說,在程序內(nèi)出現(xiàn)這樣的異常時(shí),即使沒有try...catch語(yǔ)句去捕獲它們,也沒有Throws語(yǔ)句去拋出它們,程序還是會(huì)被編譯通過。例如divide()方法的參數(shù)b為0, 執(zhí)行a/b操作時(shí)會(huì)出現(xiàn)ArithmeticException異常,它屬于運(yùn)行時(shí)異常,Java編譯器不會(huì)檢查它。

public int divide(int a, int b) { return a/b; //當(dāng)參數(shù)b為0, 拋出ArithmeticException}深入解析

運(yùn)行時(shí)異常表示無(wú)法讓程序恢復(fù)運(yùn)行的異常,導(dǎo)致這類異常的原因時(shí)進(jìn)行了不當(dāng)?shù)牟僮鳌R坏┏霈F(xiàn)錯(cuò)誤操作,建議終止程序,因此Java編譯器不檢查此類異常。

運(yùn)行時(shí)異常,應(yīng)當(dāng)盡量的避免。在程序的調(diào)試階段,遇到此類異常的正確做法是改進(jìn)程序的設(shè)計(jì)和實(shí)現(xiàn)方式,修改程序的錯(cuò)誤,避免出現(xiàn)這類異常。捕獲它并使程序繼續(xù)運(yùn)行并不是明智的選擇。

對(duì)比

與Error類對(duì)比:

相同點(diǎn):

1)Java編譯器不會(huì)去檢查它們;

2)運(yùn)行時(shí)出現(xiàn)它們,都會(huì)導(dǎo)致程序終止;

區(qū)別:

1)Error類及其子類一般都是由Java虛擬機(jī)拋出的,在JDK預(yù)定義了一些錯(cuò)誤類,比如OutOfMemoryErrorStackOutofMemoryError; runtimeException表示程序代碼的錯(cuò)誤;

2)Error類一般不會(huì)擴(kuò)展來創(chuàng)建用戶的自定義用戶類;RuntimeException時(shí)可以擴(kuò)展的,用戶可以根據(jù)自己的需求來創(chuàng)建相關(guān)的運(yùn)行時(shí)異常。

受檢查異常 除了RuntimeException及其子類外,其他Exception類及其子類都屬于受檢查異常(Checked Exception)。這種異常的特點(diǎn)是Java編譯器會(huì)檢查她們。也就是說,當(dāng)程序內(nèi)出現(xiàn)此類異常時(shí),要么用try...catch語(yǔ)句去捕獲異常,要么用Throws語(yǔ)句去拋出異常,否則會(huì)出現(xiàn)編譯不通過的情況。

3.3 一些未經(jīng)檢查的RuntimeException

java.lang.ArithimeticException

算術(shù)異常,如除數(shù)為0;

java.lang.NullPointerException

空指針引用,如沒用指定一個(gè)Reference,進(jìn)行使用;即單有指針,但未有指向的數(shù)據(jù)空間,就調(diào)用程序。

java.lang.ArrayIndexOutofBoundsException

數(shù)組越界;因?yàn)閿?shù)組的下標(biāo)是從0開始計(jì)算,而size()或length是從1開始計(jì)算的。所以不小心會(huì)產(chǎn)生調(diào)用越界的異常情況。

java.lang.ClassCastException

數(shù)據(jù)類型轉(zhuǎn)換異常。在強(qiáng)制類型轉(zhuǎn)換 和 反射創(chuàng)建對(duì)象的時(shí)候會(huì)經(jīng)常遇見此類異常。

java.lang.NumberFormatException

數(shù)據(jù)格式異常,如Integer.parseInt('a');

java.lang.NegativeArraySizeException

數(shù)組的長(zhǎng)度在聲明的時(shí)候,為負(fù)數(shù)。

4. 創(chuàng)建屬于自己的異常

4.1 異常的處理和聲明

自己主動(dòng)使用throw語(yǔ)句的時(shí)候代碼會(huì)拋出異常;使用try...catch...finally語(yǔ)句在代碼內(nèi)處理異常 或者 throw語(yǔ)句在方法聲明上拋出;

異常處理語(yǔ)句的語(yǔ)法規(guī)則如下:

try代碼塊不能脫離catch代碼塊或finally代碼塊而單獨(dú)存在。try代碼塊后面至少有一個(gè)catch代碼塊或finally代碼塊。

try代碼塊后面可以有零個(gè)或多個(gè)catch代碼塊,還可以有零個(gè)或至多一個(gè)finally代碼塊。如果catch代碼塊和finally代碼塊并存,finally代碼塊必須在catch代碼塊后面。

try代碼塊后面可以只跟finally代碼塊。在try代碼塊中定義的變量的作用域?yàn)閠ry代碼塊,在catch代碼塊和finally代碼塊中不能訪問該變量。當(dāng)try代碼塊后面有多個(gè)catch代碼塊時(shí),Java虛擬機(jī)會(huì)把實(shí)際拋出的異常對(duì)象依次和各個(gè)catch代碼塊聲明的異常類型匹配,如果異常對(duì)象為某個(gè)異常或其子類的實(shí)例,就執(zhí)行這個(gè)catch代碼塊,而不會(huì)再執(zhí)行其他的catch代碼塊。如果一個(gè)方法可能出現(xiàn)受檢查異常,要么用try…catch語(yǔ)句捕獲,要么用throws子句聲明將它拋出。throw語(yǔ)句后面不允許緊跟其它語(yǔ)句,因?yàn)檫@些語(yǔ)句永遠(yuǎn)不會(huì)被執(zhí)行。

4.2 編寫/使用自己的異常

在特定的領(lǐng)域,可以通過擴(kuò)展Exception類或者RuntimeException類來進(jìn)行擴(kuò)展創(chuàng)建自定義的異常。異常類包含了異常的相關(guān)信息。這有助于負(fù)責(zé)異常捕獲的catch代碼塊,正確的處理異常。

package com.us.demo.exception;public class MyExceptionTest{ public static void addUser() throws MyException{ System.out.println("添加用戶"); } public static void main(String []args){ addUser();// it is ok try{ addUser();// it is ok }catch(MyException myEx){ myEx.printStackTrace(); } } }class MyException extends RuntimeException{ public MyException(){ } public MyException(String message){ super(message); }}

5. 斷言

假設(shè)要進(jìn)行如下的計(jì)算:

double y = Math.sqrt(x);

為了讓程序健壯,你會(huì)先進(jìn)行測(cè)試檢查并拋出異常而不讓x的值為負(fù)數(shù)。

if(x<0) throw new IllealArgumentException("x < 0");

但是,就算是測(cè)試結(jié)束了,以后實(shí)際運(yùn)行時(shí)x的值不會(huì)小于0。這種測(cè)試代碼會(huì)一直保留在你的程序中。如果程序中有太多的檢查,程序的運(yùn)行就會(huì)慢好多。

如果在測(cè)試階段會(huì)有這種檢查,而在發(fā)布階段能自動(dòng)刪除這些東西。該多好! 這就是斷言機(jī)制。

斷言使用

在JDK1.4中,Java語(yǔ)言引入一個(gè)新的關(guān)鍵字: assert。 該關(guān)鍵字有兩種形式:

assert 條件 以及 assert 條件: 表達(dá)式

這兩種形式都會(huì)對(duì)條件進(jìn)行評(píng)估,如果結(jié)果為假則拋出AssertionError。 在第二種形式中,表達(dá)式會(huì)傳入AssertionError的構(gòu)造器并轉(zhuǎn)成一個(gè)消息字符串。

表達(dá)式字符串部分的唯一目的就是生成一個(gè)消息字符串。AssertionError對(duì)象并不存儲(chǔ)表達(dá)式的值,因此你不可能在以后獲取它。

要斷言x不是負(fù)數(shù),只需要使用如下簡(jiǎn)單的語(yǔ)句:assert x >= 0 ;

或者你可以將x的值傳遞給AssertionError對(duì)象,從而可以在以后顯示: assert x >= 0 : x;

斷言內(nèi)容代碼編譯

因?yàn)閍ssert是一個(gè)新的關(guān)鍵字,因此在使用時(shí)需要告訴編譯器你編譯所使用jdk的版本號(hào)。

javac -source 1.4 MyClass.java

在jdk的后續(xù)版本中,對(duì)斷言的支持成為默認(rèn)特性(我們使用的是JDK5.0以上,使用不需要使用這個(gè)編譯,默認(rèn)就支持的)。

斷言內(nèi)容代碼執(zhí)行

默認(rèn)情況下,斷言是關(guān)閉的。要通過-enableassertions或者-ea選項(xiàng)來運(yùn)行程序以打開斷言:

java -enableassertions com.briup.ch07.Xxxx java -ea com.briup.ch07.Xxxx

打開或關(guān)閉斷言是類裝載器的功能。當(dāng)斷言功能被關(guān)閉時(shí),類裝載器會(huì)跳過那些和斷言相關(guān)的代碼,因此不會(huì)降低程序運(yùn)行速度。

注意:使用eclipse運(yùn)行代碼的時(shí)候也是可以傳參數(shù)的(包括倆種參數(shù))

java -xx com.briup.ch07.Test yy

xx是給JVM傳的參數(shù) yy是給Test類的main方法傳的參數(shù)

斷言舉例

package com.us.demo.exception;public class AssertTest { public static void judge(int x){ assert x >= 0 : true; } public static void main(String []args){ judge(1); judge(-2);// //Exception in thread "main" java.lang.AssertionError// at com.us.demo.exception.AssertTest.judge(AssertTest.java:5)// at com.us.demo.exception.AssertTest.main(AssertTest.java:9) }}

Eclipse 調(diào)試技巧


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 厦门市| 宁都县| 崇明县| 澄江县| 紫金县| 清新县| 绥化市| 东乡县| 湘潭县| 尼木县| 桃园县| 正定县| 乐亭县| 巨鹿县| 肃南| 朝阳区| 沧源| 仲巴县| 五指山市| 开远市| 萨嘎县| 江阴市| 奉新县| 荃湾区| 沂源县| 清水县| 稷山县| 浦县| 台中市| 永年县| 托克逊县| 阳西县| 博兴县| 遂平县| 长葛市| 明光市| 抚顺市| 石渠县| 内江市| 友谊县| 杭锦后旗|