引言
? ? 我們?cè)趈ava的學(xué)習(xí)之中可能會(huì)聽到異常這個(gè)詞,那么當(dāng)程序出現(xiàn)異常之后,后面的程序還能正常運(yùn)行嗎,我們又該如何處理異常呢,本文就帶你詳細(xì)了解java中的異常。
異常的概念:
? ? ? 在生活中,我們時(shí)常會(huì)感覺到不舒服,頭疼,程序中也是一樣的,程序員們每天可能會(huì)書寫大量的代碼,有時(shí)代碼難免會(huì)有些問題,比如:數(shù)據(jù)格式不對(duì),或者數(shù)據(jù)運(yùn)算有問題。在java中,將程序在執(zhí)行過程中不正常的行為,統(tǒng)稱為異常。
這里給大家舉幾個(gè)例子:
算術(shù)運(yùn)算異常:
System.out.println(100/0);
比如這行代碼,顯然0不能作為除數(shù),所以運(yùn)行時(shí)會(huì)發(fā)生異常。
數(shù)組越界異常:
int[] arr=new int[10];
System.out.println(arr[10]);
異常的分類:
我們發(fā)現(xiàn),在程序出現(xiàn)不同的問題的時(shí)候,報(bào)的異常信息也是不一樣的,這是因?yàn)楫惓V惺欠趾芏喾N類的,面對(duì)不同的異常,會(huì)打印不同的信息。比如我們剛才看到的:數(shù)組越界異常,算數(shù)運(yùn)算異常。
? ? ? 這里的Throwable是異常大類體系中的頂層,由次派生出Error和Expecption兩種子類,
Error:這種屬于比較嚴(yán)重的問題,一旦出現(xiàn)這種問題,我們一般說程序運(yùn)行時(shí)出現(xiàn)了錯(cuò)誤。(比如棧溢出)。
Expecption:這種異常,程序員直接對(duì)代碼進(jìn)形一定的修改,就可以使程序繼續(xù)運(yùn)行了,我們平時(shí)所說的異常一般指的就是Expecption。
我們可以按照異常發(fā)生的時(shí)間的不同可以分為:
- 編譯時(shí)異常
即在程序編寫的時(shí)候就發(fā)生的異常,有時(shí)也稱為受檢查異常(ps:其實(shí)受的就是編譯器的檢查)
class Person{
String name;
int age;
@Override
public Person clone() {
return (Person)super.clone();
}
}
2.運(yùn)行時(shí)異常:
在程序運(yùn)行時(shí)發(fā)生的異常,稱為運(yùn)行時(shí)異常,也稱為(非受查異常)比如NULLPointerException,以及我們剛開始就講到的算數(shù)運(yùn)算異常。
如何處理異常:
防御型編程(LBYL):
LBYL:即在程序運(yùn)行之前就做了充分的檢查,即事前防御。
boolean ret = false;
ret = 登陸游戲();
if (!ret) {
處理登陸游戲錯(cuò)誤;
return;
}
ret = 開始匹配();
if (!ret) {
處理匹配錯(cuò)誤;
return;
}
ret = 游戲確認(rèn)();
if (!ret) {
處理游戲確認(rèn)錯(cuò)誤;
return;
}
ret = 選擇英雄();
if (!ret) {
處理選擇英雄錯(cuò)誤;
return;
這樣的代碼, 將和正常代碼混在了一起,比較混亂,代碼的可讀性變差。
時(shí)候認(rèn)錯(cuò)型(EAFP):
這里的意思是先寫代碼,等到遇到問題了在處理(這是常用的處理異常方法)。給大家舉個(gè)例子幫助理解:
try {
登陸游戲();
開始匹配();
游戲確認(rèn)();
選擇英雄();
載入游戲畫面();
...
} catch (登陸游戲異常) {
處理登陸游戲異常;
} catch (開始匹配異常) {
處理開始匹配異常;
} catch (游戲確認(rèn)異常) {
處理游戲確認(rèn)異常;
} catch (選擇英雄異常) {
處理選擇英雄異常;
} catch (載入游戲畫面異常) {
處理載入游戲畫面異常;
}
這是一段偽代碼哦?。。?!異常
在處理異常的時(shí)候,我們將經(jīng)常會(huì)用到5個(gè)關(guān)鍵字:throw,try,catch,final,throws?
異常的拋出:
當(dāng)程序出現(xiàn)異常的時(shí)候,我們需要將異常的情況報(bào)告給調(diào)用者,我們可以使用Java中的提供的throw關(guān)鍵字,拋出一個(gè)指定的異常對(duì)象,將錯(cuò)誤的信息告知給調(diào)用者。
public static int getElement(int[] array,int index){
if(arrar==null){
throw new NUllPointException("形參為空");
}
}
【注意事項(xiàng)】
1. throw 必須寫在方法體內(nèi)部2. 拋出的對(duì)象必須是 Exception 或者 Exception 的子類對(duì)象3. 如果拋出的是 RunTimeException 或者 RunTimeException 的子類,則可以不用處理,直接交給 JVM 來處理4. 如果拋出的是編譯時(shí)異常,用戶必須處理,否則無法通過編譯5. 異常一旦拋出,其后的代碼就不會(huì)執(zhí)行
?異常的捕獲:
? ? ?異常的捕獲,即異常的處理方式,主要分為兩種:throws,和try-catch捕獲處理。
throw即對(duì)異常做了一個(gè)聲明,告訴程序我知道這里有一個(gè)異常,但是并沒有具體將異常處理,而try-catch則是將可能出錯(cuò)的代碼放到中,在catch()匹配捕獲的異常然后在方法體里面對(duì)異常進(jìn)行處理,下面會(huì)有例子幫助你理解的~~
這里先是舉一個(gè)throw的例子:
public static void func(int[] array) throws Exception {
if(array == null) {
throw new Exception("傳個(gè)參數(shù)看看..."+array);
}
}
//并沒有處理異常
try-catch
public static void main3(String[] args) {
try {
int[] array = null;
System.out.println(array.length);
//System.out.println("hahaha......");
}catch (ArithmeticException e) {
e.printStackTrace();
System.out.println("處理ArithmeticException異常....");
}catch (NullPointerException e) {
e.printStackTrace();
System.out.println("處理NullPointerException異常....");
}
System.out.println("程序繼續(xù)執(zhí)行.....");
}
這里是發(fā)生的空指針異常,所以應(yīng)該是第二個(gè)catch捕捉成功。
需要注意:try如果有多個(gè)異常,只會(huì)捕獲第一個(gè)異常哦?。?!
finally關(guān)鍵字:
? ? ? ?在編寫java程序的時(shí)候,無論程序是否發(fā)生異常,我們都要執(zhí)行一些特定的代碼,比如,當(dāng)你瀏覽的網(wǎng)頁出錯(cuò)時(shí),應(yīng)該輸出提示信息。而finally關(guān)鍵字就是來解決這種問題的。下面還是一代嗎的形式給大家演示一下。
語法格式:
try{
// 可能會(huì)發(fā)生異常的代碼
}catch(異常類型 e){
// 對(duì)捕獲到的異常進(jìn)行處理
}finally{
// 此處的語句無論是否發(fā)生異常,都會(huì)被執(zhí)行到
}
// 如果沒有拋出異常,或者異常被捕獲處理了,這里的代碼也會(huì)執(zhí)行
舉個(gè)例子:
public static void main(String[] args) {
try{
int[] arr = {1,2,3};
arr[100] = 10;
arr[0] = 10;
}catch (ArrayIndexOutOfBoundsException e){
System.out.println(e);
}finally {
System.out.println("finally中的代碼一定會(huì)執(zhí)行");
}
System.out.println("如果沒有拋出異常,或者異常被處理了,try-catch后的代碼也會(huì)執(zhí)行");
}
我們知道了finally一般是在異常發(fā)生之后執(zhí)行的,這里需要特別說明:finally中的代碼一定會(huì)執(zhí)行,并且由于它的位置在異常之后,常常在程序的結(jié)尾,處理一些善后工作。并且,在try-catch中如果有return他會(huì)先執(zhí)行后面的finally中的語句,后return,如果你的finally中有return那么會(huì)優(yōu)先執(zhí)行finally中的return,而不執(zhí)行try-catch中的return?。?!
【 異常處理流程總結(jié) 】
- 程序先執(zhí)行 try 中的代碼
- 如果 try 中的代碼出現(xiàn)異常, 就會(huì)結(jié)束 try 中的代碼, 看和 catch 中的異常類型是否匹配.
- 如果找到匹配的異常類型, 就會(huì)執(zhí)行 catch 中的代碼
- 如果沒有找到匹配的異常類型, 就會(huì)將異常向上傳遞到上層調(diào)用者.
- 無論是否找到匹配的異常類型, finally 中的代碼都會(huì)被執(zhí)行到(在該方法結(jié)束之前執(zhí)行).
- 如果上層調(diào)用者也沒有處理的了異常, 就繼續(xù)向上傳遞.
- 一直到 main 方法也沒有合適的代碼處理異常, 就會(huì)交給 JVM 來進(jìn)行處理, 此時(shí)程序就會(huì)異常終止
?
自定義異常類:
在我們寫代碼的時(shí)候。有時(shí)想要對(duì)可能出現(xiàn)問題的代碼進(jìn)行捕獲,但是往往有的異常編譯器并沒有給我們提供,此時(shí)我們就需要自己定義異常類去完成異常的報(bào)錯(cuò)。
比如這里,我們實(shí)現(xiàn)一個(gè)簡(jiǎn)單的用戶個(gè)人信息的登錄系統(tǒng):
class UserNameException extends Exception {
public UserNameException(String message) {
super(message);
}
}
class PasswordException extends Exception {
public PasswordException(String message) {
super(message);
}
}
public class LogIn {
private String userName = "admin";
private String password = "123456";
public static void loginInfo(String userName, String password)
throws UserNameException,PasswordException{
if (!userName.equals(userName)) {
throw new UserNameException("用戶名錯(cuò)誤!");
}
if (!password.equals(password)) {
throw new PasswordException("用戶名錯(cuò)誤!");
}
System.out.println("登陸成功");
}
public static void main(String[] args) {
try {
loginInfo("admin", "123456");
} catch (UserNameException e) {
e.printStackTrace();
} catch (PasswordException e) {
e.printStackTrace();//這個(gè)是可以顯示你出現(xiàn)異常具體的地方
}
}
}
注意事項(xiàng)
- 自定義異常通常會(huì)繼承自 Exception 或者 RuntimeException
- 繼承自 Exception 的異常默認(rèn)是受查異常
- 繼承自 RuntimeException 的異常默認(rèn)是非受查異常
好了,今天就分享到這里了,喜歡就一鍵三連,我們下次再見~~文章來源:http://www.zghlxwxcb.cn/news/detail-842321.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-842321.html
到了這里,關(guān)于【JAVASE】帶你一文了解java中異常捕獲的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!