Java中的異常處理機(jī)制try-catch詳解
一、異常概述
在使用計(jì)算機(jī)語(yǔ)言進(jìn)行項(xiàng)目開(kāi)發(fā)的過(guò)程中,即使程序員把代碼寫(xiě)得盡善盡美,在系統(tǒng)的運(yùn)行過(guò)程中仍然會(huì)遇到一些問(wèn)題,因?yàn)楹芏鄦?wèn)題不是靠代碼能夠避免的,比如:客戶(hù)輸入數(shù)據(jù)的格式問(wèn)題,讀取文件是否存在 ,網(wǎng)絡(luò)是否始終保持通暢等等。
異常:指的是程序在執(zhí)行過(guò)程中,出現(xiàn)的非正常情況,如果不處理最終會(huì)導(dǎo)致JVM的非正常停止。
異常指的并不是語(yǔ)法錯(cuò)誤和邏輯錯(cuò)誤。語(yǔ)法錯(cuò)了,編譯不通過(guò),不會(huì)產(chǎn)生字節(jié)碼文件,根本不能運(yùn)行。
代碼邏輯錯(cuò)誤,只是沒(méi)有得到想要的結(jié)果,例如:求a與b的和,你寫(xiě)成了a-b
1、異常的拋出機(jī)制
Java中是如何表示不同的異常情況,又是如何讓程序員得知,并處理異常的呢?
Java中把不同的異常用不同的類(lèi)表示,一旦發(fā)生某種異常,就創(chuàng)建該異常類(lèi)型的對(duì)象,并且拋出(throw)。然后程序員可以捕獲(catch)到這個(gè)異常對(duì)象,并處理;如果沒(méi)有捕獲(catch)這個(gè)異常對(duì)象,那么這個(gè)異常對(duì)象將會(huì)導(dǎo)致程序終止。
舉例:
運(yùn)行下面的程序,程序會(huì)產(chǎn)生一個(gè)數(shù)組角標(biāo)越界異常ArrayIndexOfBoundsException。我們通過(guò)圖解來(lái)解析下異常產(chǎn)生和拋出的過(guò)程。
2、如何對(duì)待異常
對(duì)于程序出現(xiàn)的異常,一般有兩種解決方法:一是遇到錯(cuò)誤就終止程序的運(yùn)行。另一種方法是程序員在編寫(xiě)程序時(shí),就充分考慮到各種可能發(fā)生的異常和錯(cuò)誤,極力預(yù)防和避免。實(shí)在無(wú)法避免的,要編寫(xiě)相應(yīng)的代碼進(jìn)行異常的檢測(cè)、以及 異常的處理,保證代碼的 健壯性。
3、異常的體系結(jié)構(gòu)
3.1、Throwable
java.lang.Throwable:異常體系的父類(lèi)
Throwable中的常用方法:
- public void printStackTrace():打印異常的詳細(xì)信息。
包含了異常的類(lèi)型、異常的原因、異常出現(xiàn)的位置、在開(kāi)發(fā)和調(diào)試階段都得使用printStackTrace。
- public String getMessage():獲取發(fā)生異常的原因。
3.2、Error和Exception
Throwable可分為兩類(lèi):Error和Exception。分別對(duì)應(yīng)著java.lang.Error與java.lang.Exception 兩個(gè)類(lèi)。
Error:Java虛擬機(jī)無(wú)法解決的嚴(yán)重問(wèn)題。如:JVM系統(tǒng)內(nèi)部錯(cuò)誤、資源耗盡等嚴(yán)重情況。一般不編寫(xiě)針對(duì)性的代碼進(jìn)行處理。
- 例如:StackOverflowError(棧內(nèi)存溢出)和OutOfMemoryError(堆內(nèi)存溢出,簡(jiǎn)稱(chēng)OOM)。
Exception: 其它因編程錯(cuò)誤或偶然的外在因素導(dǎo)致的一般性問(wèn)題,需要使用針對(duì)性的代碼進(jìn)行處理,使程序繼續(xù)運(yùn)行。否則一旦發(fā)生異常,程序也會(huì)掛掉。例如:
- 空指針訪(fǎng)問(wèn)
- 試圖讀取不存在的文件
- 網(wǎng)絡(luò)連接中斷
- 數(shù)組角標(biāo)越界
3.3、編譯時(shí)異常和運(yùn)行時(shí)異常

編譯時(shí)期異常(即checked異常、受檢異常):在代碼編譯階段,編譯器就能明確 警示 當(dāng)前代碼 可能發(fā)生(不是一定發(fā)生) xx異常,并 明確督促 程序員提前編寫(xiě)處理它的代碼。如果程序員 沒(méi)有編寫(xiě) 對(duì)應(yīng)的異常處理代碼,則編譯器就會(huì)直接判定編譯失敗,從而不能生成字節(jié)碼文件。通常,這類(lèi)異常的發(fā)生不是由程序員的代碼引起的,或者不是靠加簡(jiǎn)單判斷就可以避免的,例如:FileNotFoundException(文件找不到異常)。
運(yùn)行時(shí)期異常(即runtime異常、unchecked異常、非受檢異常):在代碼編譯階段,編譯器完全不做任何檢查,無(wú)論該異常是否會(huì)發(fā)生,編譯器都不給出任何提示。只有等代碼運(yùn)行起來(lái)并確實(shí)發(fā)生了xx異常,它才能被發(fā)現(xiàn)。通常,這類(lèi)異常是由程序員的代碼編寫(xiě)不當(dāng)引起的,只要稍加判斷,或者細(xì)心檢查就可以避免。
- java.lang.RuntimeException類(lèi)及它的子類(lèi)都是運(yùn)行時(shí)異常。比如:ArrayIndexOutOfBoundsException數(shù)組下標(biāo)越界異常,ClassCastException類(lèi)型轉(zhuǎn)換異常。
運(yùn)行時(shí)異常:
ArrayIndexOutOfBoundsException:角標(biāo)越界
NullPointException:空指針異常
ClassCastException:類(lèi)型轉(zhuǎn)換異常
NumberFormatException:無(wú)法轉(zhuǎn)化異常
InputMismatchException:輸入類(lèi)型異常
ArithmeticException:算術(shù)異常
編譯型異常
ClassNotFoundException
FileNotFoundException
IOException
二、異常的處理方式一 try-catch的使用
在編寫(xiě)程序時(shí),經(jīng)常要在可能出現(xiàn)錯(cuò)誤的地方加上檢測(cè)的代碼,如進(jìn)行x/y運(yùn)算時(shí),要檢測(cè)分母為0,數(shù)據(jù)為空,輸入的不是數(shù)據(jù)而是字符 等。過(guò)多的if-else分支會(huì)導(dǎo)致程序的代碼加長(zhǎng)、臃腫 ,可讀性差,程序員需要花很大的精力“ 堵漏洞”。因此采用異常處理機(jī)制。
Java異常處理
Java采用的異常處理機(jī)制,是將異常處理的程序代碼集中在一起 ,與正常的程序代碼分開(kāi),使得程序簡(jiǎn)潔、優(yōu)雅,并易于維護(hù)。
Java異常處理的方式:
方式一:try-catch-finally
方式二:throws+異常類(lèi)型
1、過(guò)程1:拋
程序在執(zhí)行的過(guò)程當(dāng)中,一旦出現(xiàn)異常,就會(huì)在出現(xiàn)異常的代碼處,生成對(duì)應(yīng)的異常類(lèi)對(duì)象,并將此對(duì)象拋出。
一旦拋出此程序不執(zhí)行其后面的代碼。
2、過(guò)程2:抓
針對(duì)過(guò)程1中拋出的對(duì)象,進(jìn)行捕獲處理。此捕獲處理的過(guò)程,就成為抓
一旦將異常進(jìn)行處理,代碼就可以急促執(zhí)行。
try{
...//可能出現(xiàn)的異常代碼
}catch(異常類(lèi)型1 e){
...//當(dāng)產(chǎn)生異常類(lèi)型1 異常時(shí)的處置措施
}catch(異常類(lèi)型2 e){
...//當(dāng)產(chǎn)生異常類(lèi)型2 異常時(shí)的處置措施
}finally{
...//無(wú)論是否發(fā)生異常,都無(wú)條件執(zhí)行的語(yǔ)句
}import java.util.InputMismatchException;
import java.util.Scanner;
/**
* package:PACKAGE_NAME
*
* @Author jimmy-yan
* @Create 2024/11/18 17:14
*/
public class ExceptionTest {
public static void main(String[] args) {
ExceptionTest e = new ExceptionTest();
e.test();
}
public void test() {
try {
Scanner scanner = new Scanner(System.in);
int num = scanner.nextInt();
System.out.println(num);
} catch (InputMismatchException e) {
System.out.println("出現(xiàn)了InputMismatchException異常");
} catch (RuntimeException e) {
System.out.println("出現(xiàn)了RuntimeException異常");
}
System.out.println("異常處理結(jié)束,代碼繼續(xù)執(zhí)行");
}
}3、使用細(xì)節(jié)
1、將可能出現(xiàn)異常的代碼聲明在try語(yǔ)句中。一旦代碼出現(xiàn)異常,就會(huì)自動(dòng)生成一個(gè)對(duì)應(yīng)異常類(lèi)的對(duì)象。并將此對(duì)象拋出。
2、針對(duì)于try中拋出的異常類(lèi)的對(duì)象,使用之后的catch語(yǔ)句進(jìn)行匹配,一旦匹配上,就進(jìn)入catch語(yǔ)句塊進(jìn)行處理。
3、一旦處理結(jié)束,代碼就可以繼續(xù)向下執(zhí)行。
4、如果聲明了多個(gè)catch結(jié)構(gòu),不同的異常類(lèi)型在子父關(guān)系的情況下,誰(shuí)聲明在上面,誰(shuí)聲明在下面都可以。如果多個(gè)異常類(lèi)型滿(mǎn)足子父類(lèi)的關(guān)系,必須將子類(lèi)聲明在父類(lèi)結(jié)構(gòu)的上面。否則報(bào)錯(cuò)。
5、catch中異常處理的方式:
a、自己編寫(xiě)輸出的語(yǔ)句;
b、printStackTrace:打印異常的詳細(xì)信息;(推薦)
6、try中聲明的變量,出了try結(jié)構(gòu)之后,就不可以進(jìn)行調(diào)用了。
4、運(yùn)行時(shí)異常案例
import java.util.InputMismatchException;
import java.util.Scanner;
/**
* package:PACKAGE_NAME
*
* @Author jimmy-yan
* @Create 2024/11/18 17:14
*/
public class ExceptionTest {
public static void main(String[] args) {
ExceptionTest e = new ExceptionTest();
e.test1();
}
public void test1() {
try {
String str = "123";
str = "abc";
int i = Integer.parseInt(str);
System.out.println(i);
}catch (NumberFormatException e){
e.printStackTrace();
}
System.out.println("程序執(zhí)行結(jié)束");
}
}
5、編譯型異常案例
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.InputMismatchException;
import java.util.Scanner;
/**
* package:PACKAGE_NAME
*
* @Author jimmy-yan
* @Create 2024/11/18 17:14
*/
public class ExceptionTest {
public static void main(String[] args) {
ExceptionTest e = new ExceptionTest();
// e.test();
// e.test1();
e.test2();
}
public void test() {
try {
Scanner scanner = new Scanner(System.in);
int num = scanner.nextInt();
System.out.println(num);
} catch (InputMismatchException e) {
System.out.println("出現(xiàn)了InputMismatchException異常");
} catch (RuntimeException e) {
System.out.println("出現(xiàn)了RuntimeException異常");
}
System.out.println("異常處理結(jié)束,代碼繼續(xù)執(zhí)行");
}
public void test1() {
try {
String str = "123";
str = "abc";
int i = Integer.parseInt(str);
System.out.println(i);
} catch (NumberFormatException e) {
e.printStackTrace();
}
System.out.println("程序執(zhí)行結(jié)束");
}
public void test2() {
try {
File file = new File("D:\\hello.txt");
FileInputStream fis = new FileInputStream(file); //可能報(bào)FileFonudException
int data = fis.read(); //可能報(bào)IOException
while (data != -1) {
System.out.println((char) data);
data = fis.read(); //可能報(bào)IOException
}
fis.close(); //可能報(bào)IOException
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}6、開(kāi)發(fā)體會(huì)
對(duì)于運(yùn)行時(shí)異常:
開(kāi)發(fā)中,通常就不進(jìn)行顯示的處理了,一旦在程序執(zhí)行中,出現(xiàn)了運(yùn)行時(shí)異常,那么就根據(jù)異常的提示信息修改代碼即可。
對(duì)于編譯型異常:
一定要處理,否則代碼不能執(zhí)行通過(guò)
到此這篇關(guān)于Java-異常處理機(jī)制-try-catch的文章就介紹到這了,更多相關(guān)Java異常處理機(jī)制try-catch內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java中g(shù)etResourceAsStream用法分析
這篇文章主要介紹了Java中g(shù)etResourceAsStream用法,較為詳細(xì)的分析了getResourceAsStream的功能及用法,需要的朋友可以參考下2015-06-06
SVN報(bào)錯(cuò):Error Updating changes:svn:E155037的解決方案
今天小編就為大家分享一篇關(guān)于SVN報(bào)錯(cuò):Error Updating changes:svn:E155037的解決方案,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-01-01
Java使用synchronized實(shí)現(xiàn)互斥鎖功能示例
這篇文章主要介紹了Java使用synchronized實(shí)現(xiàn)互斥鎖功能,結(jié)合實(shí)例形式分析了Java使用synchronized互斥鎖功能簡(jiǎn)單實(shí)現(xiàn)方法與操作技巧,需要的朋友可以參考下2020-05-05
Java數(shù)據(jù)結(jié)構(gòu)順序表從零基礎(chǔ)到精通進(jìn)階
程序中經(jīng)常需要將一組數(shù)據(jù)元素作為整體管理和使用,需要?jiǎng)?chuàng)建這種元素組,用變量記錄它們,傳進(jìn)傳出函數(shù)等。一組數(shù)據(jù)中包含的元素個(gè)數(shù)可能發(fā)生變化,順序表則是將元素順序地存放在一塊連續(xù)的存儲(chǔ)區(qū)里,元素間的順序關(guān)系由它們的存儲(chǔ)順序自然表示2022-03-03

