Java例外處理
目錄- Java例外處理
- 一、例外概述與例外體系結構
- 1.1 Java 引入例外的原因:
- 1.2 例外的概念:
- 1.3 Java中的例外事件的分類:
- 二、常見例外
- 三、Java 例外處理機制:
- 3.1 簡介:
- 3.2 Java 例外處理機制之一:try-catch-finally
- 3.3 Java 例外處理機制之二:throws + 例外型別
- 四、手動拋出例外(throw)
- 五、用戶自定義例外類
- 一、例外概述與例外體系結構
一、例外概述與例外體系結構
1.1 Java 引入例外的原因:
在進行專案開發的程序中,即使程式員把代碼寫得完美, 在系統的運行程序中仍然會遇到一些問題,因為很多問題不是靠代碼能夠避免的,比如:客戶輸入資料的格式,讀取檔案是否存在,網路是否始終保持通暢等等,
1.2 例外的概念:
在Java語言中,將程式執行中發生的不正常情況稱為“例外” ,(開發程序中的語法錯誤和邏輯錯誤不是例外)
1.3 Java中的例外事件的分類:
- Error:Java 虛擬機無法解決的嚴重問題,
例如:JVM系統內部錯誤、資源 耗盡等嚴重情況,比如:StackOverflowError 和 OOM,一般不撰寫針對性的代碼進行處理,
- Exception(狹義的例外,Java中所講的例外處理即處理 Exception):其它因編程錯誤或偶然的外在因素導致的一般性問題,可以使用針對性的代碼進行處理,
例如:空指標訪問;試圖讀取不存在的檔案;網路連接中斷;陣列角標越界,
-
對于這些錯誤,一般有兩種解決方法:
一是遇到錯誤就終止程式的運行,
另一種方法是由程式員在撰寫程式時,就考慮到錯誤的檢測、錯誤訊息的提示,以及錯誤的處理,捕獲錯誤最理想的是在編譯期間,但有的錯誤只有在運行時才會發生, 所以捕獲的例外也分為:編譯時例外和運行時例外,
比如:除數為0,陣列下標越界等,
1.運行時例外:
是指編譯器不要求強制處置的例外,一般是指編程時的邏輯錯誤,是程式員應該積極避免其出現的例外,java.lang.RuntimeException 類及它的子類都是運行時例外,
對于這類例外,可以不作處理,因為這類例外很普遍,若全處理可能會對程式的可讀性和運行效率產生影響,
2.編譯時例外:是指編譯器要求必須處置的例外,即程式在運行時由于外界因素造成的一 般性例外,編譯器要求 Java 程式必須捕獲或宣告所有編譯時例外,
對于這類例外,如果程式不處理,可能會帶來意想不到的結果,
-
所有的例外類是從 java.lang.Exception 類繼承的子類,
Exception 類是 Throwable 類的子類,除了Exception類外,Throwable 還有一個子類Error ,

二、常見例外
| 例外 | 中文介紹 | 描述 |
|---|---|---|
| ArithmeticException | 運算異 常 | 當出現例外的運算條件時,拋出此例外,例如,一個整數"除以零"時,拋出此類的一個實體, |
| InputMismatchException | 輸入不匹配例外 | 當用戶輸入的資料型別與程式定義的資料型別不匹配時所報的例外, |
| NumberFormatException | 資料格式例外 | 當應用程式試圖將字串轉換成一種數值型別,但該字串不能轉換為適當格式時,拋出該例外, |
| ClassCastException | 型別轉換例外 | 當試圖將物件強制轉換為不是實體的子類時,拋出該例外, |
| ArrayIndexOutOfBoundsException | 陣列下標越界例外 | 用非法索引訪問陣列時拋出的例外,如果索引為負或大于等于陣列大小,則該索引為非法索引, |
| StringIndexOutOfBoundsException | 字串下標越界例外 | 此例外由 String 方法拋出,指示索引或者為負,或者超出字串的大小, |
| NullPointerException | 空指標例外 | 當應用程式試圖在需要物件的地方使用 null 時,拋出該例外, |
public class ExceptionTest {
//******************以下是編譯時例外***************************
@Test
public void test7(){
// File file = new File("hello.txt");
// FileInputStream fis = new FileInputStream(file);
//
// int data = https://www.cnblogs.com/xiaozhao01/archive/2022/07/30/fis.read();
// while(data != -1){
// System.out.print((char)data);
// data = fis.read();
// }
//
// fis.close();
}
//******************以下是運行時例外***************************
//ArithmeticException
@Test
public void test6(){
int a = 10;
int b = 0;
System.out.println(a / b);
}
//InputMismatchException
@Test
public void test5(){
Scanner scanner = new Scanner(System.in);
int score = scanner.nextInt();
System.out.println(score);
scanner.close();
}
//NumberFormatException
@Test
public void test4(){
String str ="123";
str = "abc";
int num = Integer.parseInt(str);
}
//ClassCastException
@Test
public void test3(){
Object obj = new Date();
String str = (String)obj;
}
//IndexOutOfBoundsException
@Test
public void test2(){
//ArrayIndexOutOfBoundsException
// int[] arr = new int[10];
// System.out.println(arr[10]);
//StringIndexOutOfBoundsException
String str = "abc";
System.out.println(str.charAt(3));
}
//NullPointerException
@Test
public void test1(){
String str = "abc";
str = null;
System.out.println(str.charAt(0));
}
}
三、Java 例外處理機制:
3.1 簡介:
-
Java 提供的是例外處理的抓拋模型,
程序一:"拋":
Java 程式的執行程序中如出現例外,會生成一個例外類物件,該例外物件將被提交給 Java 運行時系統,這個程序稱為拋出(throw)例外,一旦拋出物件以后,其后的代碼就不再執行,
程序二:"抓":
可以理解為例外的處理方式:① try-catch-finally ② throws
-
例外物件的生成:
-
由虛擬機自動生成:程式運行程序中,虛擬機檢測到程式發生了問題,如果在當前代碼中沒有找到相應的處理程式,就會在后臺自動創建一個對應例外類的實體 物件并拋出——自動拋出
-
由開發人員手動創建:Exception exception = new ClassCastException();——創建好的例外物件不拋出對程式沒有任何影響,和創建一個普通物件一樣,
-
-
如果一個方法內拋出例外,該例外物件會被拋給呼叫者方法中處理,如果例外沒有在呼叫者方法中處理,它繼續被拋給這個呼叫方法的上層方法,這個程序將一直繼續下去,直到例外被處理, 這一程序稱為捕獲(catch)例外,
如果一個例外回到 main() 方法,并且 main() 也不處理,則程式運行終止,
3.2 Java 例外處理機制之一:try-catch-finally
- 語法格式:
try{
// 可能出現例外的代碼
}catch(例外型別1 變數名1){
// 處理例外的方式1
}catch(例外型別2 變數名2){
// 處理例外的方式2
}catch(例外型別3 變數名3){
// 處理例外的方式3
}
....// 注意:省略號表示其他catch陳述句,而不是所有陳述句
finally{
// 一定會執行的代碼(finally可選)
}
-
說明:
(1)finally 是可選的,
(2)使用 try 將可能出現例外代碼包裝起來,在執行程序中,一旦出現例外,就會生成一個對應例外類的物件,根據此物件的型別,去catch中進行匹配,且 try 里出現例外陳述句后的陳述句不再執行,
(3)一旦 try 中的例外物件匹配到某一個 catch 時,就進入 catch 中進行例外的處理,一旦處理完成,就跳出當前的 try-catch 結構(在沒有寫finally的情況),繼續執行其后的代碼,
(4)catch 中的例外型別如果沒有子父類關系,則宣告順序無所謂,
? catch 中的例外型別如果滿足子父類關系,則要求子類一定宣告在父類的提前宣告,否則會報錯,
(5)常用的例外物件處理的方式:
? ① String getMessage()
? ② printStackTrace()
(6)在 try 結構中宣告的變數,再出了 try 結構以后,就不能再被呼叫.
(7)try-catch-finally 結構可以嵌套,
(8)try-catch-finally 結構一定是連在一起的,比如 try{} 、catch{}、finally{} 之間不能有其他的陳述句,
(9)finally中宣告的是一定會被執行的代碼,即使catch中又出現例外了,try中有return陳述句,catch中有return陳述句等情況,
(10)像資料庫連接、輸入輸出流、網路編程Socket等資源,JVM是不能自動的回收的,我們需要自己手動的進行資源的釋放,此時的資源釋放,就需要宣告在finally中,
-
例子1:
public class FinallyTest {
@Test
public void test(){
FileInputStream fis = null;
try {
File file = new File("hello.txt");
fis = new FileInputStream(file);
int data = https://www.cnblogs.com/xiaozhao01/archive/2022/07/30/fis.read();
while(data != -1){
System.out.print((char)data);
data = fis.read();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{ // try-catch-fianlly里可以嵌套使用
try {
if(fis != null)
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void testMethod(){
int num = method();
System.out.println(num);
}
public int method(){
try{
int[] arr = new int[10];
System.out.println(arr[10]);
return 1;
}catch(ArrayIndexOutOfBoundsException e){
e.printStackTrace();
return 2;
}finally{
System.out.println("一定會被執行");
return 3; // 當沒有此陳述句是num輸出為 2,當有此陳述句時輸出為 3,
}
}
}
體會:
使用try-catch-finally處理編譯時例外,是得程式在編譯時就不再報錯,但是運行時仍可能報錯,相當于我們使用try-catch-finally將一個編譯時可能出現的例外,延遲到運行時出現,
開發中,由于運行時例外比較常見,所以我們通常就不針對運行時例外撰寫try-catch-finally了,針對于編譯時例外,我們說一定要考慮例外的處理,
例子2:
public class ReturnExceptionDemo {
static void methodA() {
try {
System.out.println("進入方法A");
throw new RuntimeException("制造例外"); // 創建了一個例外物件,但沒被捕獲和輸出
}finally {
System.out.println("呼叫A方法的finally");
}
}
static void methodB() {
try {
System.out.println("進入方法B");
return;
} finally {
System.out.println("呼叫B方法的finally");
}
}
public static void main(String[] args) {
try {
methodA(); // 輸出:進入方法A && 呼叫A方法的finally
} catch (Exception e) {
System.out.println(e.getMessage()); // 輸出:制造例外
}
methodB(); // 輸出:進入方法B && 呼叫B方法的finally
}
}
/* 運行結果:
進入方法A
用A方法的finally
制造例外
進入方法B
呼叫B方法的finally
*/
3.3 Java 例外處理機制之二:throws + 例外型別
- 語法格式:
public void method() throws 例外型別{
}
- 說明:
(1) "throws + 例外型別"寫在方法的宣告處,指明此方法執行時,可能會拋出的例外型別,一旦當方法體執行時,出現例外,仍會在例外代碼處生成一個例外類的物件,此物件滿足 throws 后例外型別時,就會被拋出,例外代碼后續的代碼,就不再執行!
(2)try-catch-finally:真正的將例外給處理掉了,
? throws的方式只是將例外拋給了方法的呼叫者,并沒有真正將例外處理掉,
(3)開發中如何選擇使用 try-catch-finally 還是使用 throws ?
-
如果父類中被重寫的方法沒有 throws 方式處理例外,則子類重寫的方法也不能使用 throws,意味著如果子類重寫的方法中有例外,必須使用 try-catch-finally 方式處理,
-
執行的方法 a 中,先后又呼叫了另外的幾個方法,這幾個方法是遞進關系執行的,我們建議這幾個方法使用 throws 的方式進行處理,而執行的方法 a 可以考慮使用 try-catch-finally 方式進行處理,
四、手動拋出例外(throw)
注意:throw 后沒有 s,
public class StudentTest {
public static void main(String[] args) {
try {
Student s = new Student();
s.regist(-1001);
System.out.println(s);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
class Student{
private int id;
public void regist(int id) throws Exception {
if(id > 0){
this.id = id;
}else{
// System.out.println("您輸入的資料非法!");
// 手動拋出例外物件
throw new RuntimeException("您輸入的資料非法!");
// 或者 throw new Exception("您輸入的資料非法!");
}
}
}
簡述 throw 和 throws 的區別:
throw:表示拋出一個例外類的物件,生成例外物件的程序,宣告在方法體內,
throws:屬于例外處理的一種方式,宣告在方法宣告處,
五、用戶自定義例外類
如何自定義例外類?
-
繼承于現有的例外結構:RuntimeException、Exception,
-
提供全域常量:serialVersionUID,(序列化版本號,用來唯一識別自定義例外類),
-
提供幾個多載的構造器,
-
自定義例外最重要的是例外類的名字,當例外出現時,可以根據名字判斷例外型別,
例子:
//自定義例外類
public class EcDef extends Exception {
static final long serialVersionUID = -33875164229948L; // 序列化版本號
public EcDef() { // 多載的構造器
}
public EcDef(String msg) { // 多載的構造器
super(msg);
}
}
------------------------------------------------------------------------------------------------------------
public class EcmDef {
public static void main(String[] args) {
try{
int i = Integer.parseInt(args[0]);
int j = Integer.parseInt(args[1]);
int result = ecm(i,j);
System.out.println(result);
}catch(NumberFormatException e){
System.out.println("資料型別不一致");
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("缺少命令列引數");
}catch(ArithmeticException e){
System.out.println("分母不能為0");
}catch(EcDef e){
System.out.println(e.getMessage());
}
}
public static int ecm(int i,int j) throws EcDef{
if(i < 0 || j < 0){
throw new EcDef("分子或分母不能負數");
}
return i / j;
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/500641.html
標籤:其他
上一篇:JAVA基礎第一天
