Java 詳解異常的處理機(jī)制
1.異常概述與異常體系結(jié)構(gòu)
1.1異常概述
異常:在Java語(yǔ)言中,將程序執(zhí)行中發(fā)生的不正常情況稱為“異常”。 (開(kāi)發(fā)過(guò)程中的語(yǔ)法錯(cuò)誤和邏輯錯(cuò)誤不是異常)
Java程序在執(zhí)行過(guò)程中所發(fā)生的異常事件可分為兩類:
Error:Java虛擬機(jī)無(wú)法解決的嚴(yán)重問(wèn)題。如:JVM系統(tǒng)內(nèi)部錯(cuò)誤、資源耗盡等嚴(yán)重情況。比如:StackOverflowError和OOM。一般不編寫(xiě)針對(duì)性
的代碼進(jìn)行處理。
Exception: 其它因編程錯(cuò)誤或偶然的外在因素導(dǎo)致的一般性問(wèn)題,可以使
用針對(duì)性的代碼進(jìn)行處理。
例如:
- 空指針訪問(wèn)
- 試圖讀取不存在的文件
- 網(wǎng)絡(luò)連接中斷
- 數(shù)組角標(biāo)越界
1.2運(yùn)行時(shí)異常與編譯時(shí)異常
對(duì)于這些錯(cuò)誤,一般有兩種解決方法:一是遇到錯(cuò)誤就終止程序
的運(yùn)行。另一種方法是由程序員在編寫(xiě)程序時(shí),就考慮到錯(cuò)誤的
檢測(cè)、錯(cuò)誤消息的提示,以及錯(cuò)誤的處理。
捕獲錯(cuò)誤最理想的是在編譯期間,但有的錯(cuò)誤只有在運(yùn)行時(shí)才會(huì)發(fā)生。
比如:除數(shù)為0,數(shù)組下標(biāo)越界等
分類:編譯時(shí)異常和運(yùn)行時(shí)異常
1.運(yùn)行時(shí)異常
是指編譯器不要求強(qiáng)制處置的異常。一般是指編程時(shí)的邏輯錯(cuò)誤,是程序
員應(yīng)該積極避免其出現(xiàn)的異常。java.lang.RuntimeException類及它的子
類都是運(yùn)行時(shí)異常。
對(duì)于這類異常,可以不作處理,因?yàn)檫@類異常很普遍,若全處理可能會(huì)對(duì)
程序的可讀性和運(yùn)行效率產(chǎn)生影響。
2.編譯時(shí)異常
是指編譯器要求必須處置的異常。即程序在運(yùn)行時(shí)由于外界因素造成的一
般性異常。編譯器要求Java程序必須捕獲或聲明所有編譯時(shí)異常。
l 對(duì)于這類異常,如果程序不處理,可能會(huì)帶來(lái)意想不到的結(jié)果。
1.3異常體系結(jié)構(gòu)

2.常見(jiàn)異常
java.lang.RuntimeException
- ClassCastException
- ArrayIndexOutOfBoundsException
- NullPointerException
- ArithmeticException
- NumberFormatException
- InputMismatchException
java.io.IOExeption
- FileNotFoundException
- EOFException
java.lang.ClassNotFoundException
java.lang.InterruptedException
java.io.FileNotFoundException
java.sql.SQLException
1. ArrayIndexOutOfBoundsException
public class IndexOutExp {
public static void main(String[] args) {
String friends[] = { "lisa", "bily", "kessy" };
for (int i = 0; i < 5; i++) {
System.out.println(friends[i]); // friends[4]?
}
System.out.println("\nthis is the end");
}
}
運(yùn)行結(jié)果:數(shù)組越界異常

2.NullPointerException
public class NullRef{
int i = 1;
public static void main(String[] args){
NullRef t = new NullRef();
t = null;
System.out.println(t.i);
}
}
運(yùn)行結(jié)果:空指針異常

3.ArithmeticException
public class DivideZero{
int x;
public static void main(String[] args){
int y;
DivideZero c=new DivideZero();
y=3/c.x;
System.out.println("program ends ok!");
}
}
運(yùn)行結(jié)果:除零異常

4.ClassCastException
public class Order{
public static void main(String[] args){
Object obj = new Date();
Order order;
order = (Order) obj;
System.out.println(order);
}
}
運(yùn)行結(jié)果:類轉(zhuǎn)換異常

3.異常處理機(jī)制
3.1異常的拋出與捕獲
Java提供的是異常處理的抓拋模型
拋出異常
Java程序的執(zhí)行過(guò)程中如出現(xiàn)異常,會(huì)生成一個(gè)異常類對(duì)象,該異常對(duì)象將被提交給Java運(yùn)行時(shí)系統(tǒng),這個(gè)過(guò)程稱為拋出(throw)異常。
異常對(duì)象的生成
- 由虛擬機(jī)自動(dòng)生成:程序運(yùn)行過(guò)程中,虛擬機(jī)檢測(cè)到程序發(fā)生了問(wèn)題,如果在當(dāng)前代碼中沒(méi)有找到相應(yīng)的處理程序,就會(huì)在后臺(tái)自動(dòng)創(chuàng)建一個(gè)對(duì)應(yīng)異常類的實(shí)例對(duì)象并拋出——自動(dòng)拋出
- 由開(kāi)發(fā)人員手動(dòng)創(chuàng)建:Exception exception = new ClassCastException();——?jiǎng)?chuàng)建好的異常對(duì)象不拋出對(duì)程序沒(méi)有任何影響,和創(chuàng)建一個(gè)普通對(duì)象一樣
異常的拋出機(jī)制:

捕獲異常
如果一個(gè)方法內(nèi)拋出異常,該異常對(duì)象會(huì)被拋給調(diào)用者方法中處理。如果異常沒(méi)有在調(diào)用者方法中處理,它繼續(xù)被拋給這個(gè)調(diào)用方法的上層方法。這個(gè)過(guò)程將一直繼續(xù)下去,直到異常被處理。這一過(guò)程稱為捕獲(catch)異常。
如果一個(gè)異常回到main()方法,并且main()也不處理,則程序運(yùn)
行終止。
程序員通常只能處理Exception,而對(duì)Error無(wú)能為力。
3.2異常處理機(jī)制:try-catch-finally
異常處理是通過(guò)try-catch-finally語(yǔ)句實(shí)現(xiàn)的
try{
...... //可能產(chǎn)生異常的代碼
}
catch( ExceptionName1 e ){
...... //當(dāng)產(chǎn)生ExceptionName1型異常時(shí)的處置措施
}
catch( ExceptionName2 e ){
...... //當(dāng)產(chǎn)生ExceptionName2型異常時(shí)的處置措施
}[ finally{
...... //無(wú)論是否發(fā)生異常,都無(wú)條件執(zhí)行的語(yǔ)句
} ]
try
捕獲異常的第一步是用try{…}語(yǔ)句塊選定捕獲異常的范圍,將可能出現(xiàn)
異常的代碼放在try語(yǔ)句塊中。
catch (Exceptiontype e)
在catch語(yǔ)句塊中是對(duì)異常對(duì)象進(jìn)行處理的代碼。每個(gè)try語(yǔ)句塊可以伴隨
一個(gè)或多個(gè)catch語(yǔ)句,用于處理可能產(chǎn)生的不同類型的異常對(duì)象。
finally
捕獲異常的最后一步是通過(guò)finally語(yǔ)句為異常處理提供一個(gè)
統(tǒng)一的出口,不論在try代碼塊中是否發(fā)生了異常事件,catch語(yǔ)句是否執(zhí)
行,catch語(yǔ)句是否有異常,catch語(yǔ)句中是否有return,finally塊中的語(yǔ)句都會(huì)被執(zhí)行。
捕獲異常的有關(guān)信息:
與其它對(duì)象一樣,可以訪問(wèn)一個(gè)異常對(duì)象的成員變量或調(diào)用它的
方法。
- getMessage() 獲取異常信息,返回字符串
- printStackTrace() 獲取異常類名和異常信息,以及異常出現(xiàn)在程序中的位置。返回值void。
舉例:指針越界
public class IndexOutExp{
public static void main(String[] args){
String friends[] = { "lisa", "bily", "kessy" };
try{
for (int i = 0; i < 5; i++) {
System.out.println(friends[i]);
}
}catch (ArrayIndexOutOfBoundsException e){
System.out.println("index err");
}
System.out.println("\nthis is the end");
}
}
//程序IndexOutExp.java運(yùn)行結(jié)果:java IndexOutExp
lisa
bily
kessy
index err
this is the end
4.用戶自定義異常類
一般地,用戶自定義異常類都是RuntimeException的子類。
- 自定義異常類通常需要編寫(xiě)幾個(gè)重載的構(gòu)造器。 l 自定義異常需要提供serialVersionUID
- 自定義的異常通過(guò)throw拋出。
- 自定義異常最重要的是異常類的名字,當(dāng)異常出現(xiàn)時(shí),可以根據(jù)名字判斷異常類型。
用戶自定義異常類MyException,用于描述數(shù)據(jù)取值范圍錯(cuò)誤信息。用戶
自己的異常類必須繼承現(xiàn)有的異常類
public class Test {
private static String userName = "admin";
private static String password = "123456";
public static void main(String[] args) {
login("admin", "123456");
}
public static void login(String userName, String password) {
if (!Test.userName.equals(userName)) {
// TODO 處理用戶名錯(cuò)誤
}
if (!Test.password.equals(password)) {
// TODO 處理密碼錯(cuò)誤
}
System.out.println("登陸成功");
}
}
此時(shí)我們?cè)谔幚碛脩裘艽a錯(cuò)誤的時(shí)候可能就需要拋出兩種異常. 我們可以基于已有的異常類進(jìn)行擴(kuò)展(繼承), 創(chuàng)建和我們業(yè)務(wù)相關(guān)的異常類
class UserError extends Exception {
public UserError(String message) {
super(message);
}
}
class PasswordError extends Exception {
public PasswordError(String message) {
super(message);
}
}
此時(shí)我們的 login 代碼可以改成
public static void main(String[] args) {
try {
login("admin", "123456");
} catch (UserError userError) {
userError.printStackTrace();
} catch (PasswordError passwordError) {
passwordError.printStackTrace();
}
}
public static void login(String userName, String password) throws UserError,
PasswordError {
if (!Test.userName.equals(userName)) {
throw new UserError("用戶名錯(cuò)誤");
}
if (!Test.password.equals(password)) {
throw new PasswordError("密碼錯(cuò)誤");
}
System.out.println("登陸成功");
}
注意事項(xiàng):
自定義異常通常會(huì)繼承自 Exception 或者 RuntimeException
繼承自 Exception 的異常默認(rèn)是受查異常
繼承自 RuntimeException 的異常默認(rèn)是非受查異常
5.異常處理5個(gè)關(guān)鍵字

以上就是Java 詳解異常的處理機(jī)制的詳細(xì)內(nèi)容,更多關(guān)于Java 異常處理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
idea maven項(xiàng)目無(wú)法識(shí)別jar包里的class解決方案
這篇文章主要介紹了idea maven項(xiàng)目無(wú)法識(shí)別jar包里的class解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
Spring中利用IOC實(shí)現(xiàn)注入的方式
Spring IOC(控制反轉(zhuǎn))實(shí)現(xiàn)依賴注入,將對(duì)象創(chuàng)建和依賴關(guān)系的管理交由Spring容器處理,通過(guò)注解或XML配置,實(shí)現(xiàn)對(duì)象之間的松耦合,提高代碼復(fù)用性和可維護(hù)性2023-04-04
classloader類加載器_基于java類的加載方式詳解
下面小編就為大家?guī)?lái)一篇classloader類加載器_基于java類的加載方式詳解。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10
springboot @WebFilter注解過(guò)濾器的實(shí)現(xiàn)
這篇文章主要介紹了springboot @WebFilter注解過(guò)濾器的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03
java 運(yùn)行報(bào)錯(cuò)has been compiled by a more recent version of the J
java 運(yùn)行報(bào)錯(cuò)has been compiled by a more recent version of the Java Runtime (class file version 54.0)2021-04-04

