>[success] # java 異常
1. 在Java語言中主要指程序執行中發生的不正常情況,通過`java.lang.Throwable`類是Java語言中錯誤(Error)和異常(Exception)的超類
2. `Error`類主要用于描述**Java虛擬機無法解決的嚴重錯誤**,通常無法編碼解決,如:JVM掛掉了
3. `Exception`類主要用于描述因編程**錯誤或偶然外在因素導致的輕微錯誤**,通常可以編碼解決,如:0作為除數,`java.lang.Exception`類是所有異常的超類,主要分兩種**非檢測性異常**,**叫作檢測性異常**
* `RuntimeException` - 運行時異常,也叫作非檢測性異常(`ArithmeticException`類 - 算術異常/`ArrayIndexOutOfBoundsException`類 - 數組下標越界異常/`NullPointerException` - 空指針異常/`ClassCastException` - 類型轉換異常/`NumberFormatException `- 數字格式異常)
~~~
public class ExceptionTest {
public static void main(String[] args) {
int i = 5;
int j = 0;
// 非檢測性異常 運行時異常
System.out.println(i / j); // 編譯ok,運行階段會發生算術異常 下面的代碼不會執行
System.out.println("上面異常我不能打印");
}
}
~~~
**執行報錯信息**,當程序執行過程中發生異常但又沒有手動處理時,則由Java虛擬機采用默認方式處理異常,而默認
處理方式就是:打印異常的名稱、異常發生的原因、異常發生的位置以及終止程序

* `IOException`和`其它異常` ,也叫作檢測性異常,所謂檢測性異常就是指在編譯階段都能被編譯器檢測出來的異常

>[danger] ##### 解決異常
1. 解決異常就要增加代碼的強壯性。可以通過**if條件**判斷來避免異常的發生,但帶來的問題過多的if條件判斷會導致程序的代碼**加長、臃腫,可讀性差**,下面代碼通過if 判斷杜絕了下面會產生的異常
~~~
import java.io.IOException;
public class ExceptionPreventTest {
public static void main(String[] args) {
// 會發生算術異常
int ia = 10;
int ib = 0;
if (0 != ib) {
System.out.println(ia / ib);
}
// 數組下標越界異常
int[] arr = new int[5];
int pos = 5;
if (pos >= 0 && pos < 5) {
System.out.println(arr[pos]);
}
// 發生空指針異常
String str = null;
if (null != str) {
System.out.println(str.length());
}
// 類型轉換異常
Exception ex = new Exception();
if (ex instanceof IOException) {
IOException ie = (IOException) ex;
}
// 數字格式異常
String str2 = "123a";
if (str2.matches("\\d+")) {
System.out.println(Integer.parseInt(str2));
}
System.out.println("程序總算正常結束了!");
}
}
~~~
>[danger] ##### 采用異常的捕獲
* 語法格式
~~~
try {
編寫可能發生異常的代碼; }
catch(異常類型 引用變量名) {
編寫針對該類異常的處理代碼;
}
...
finally {
編寫無論是否發生異常都要執行的代碼;
}
~~~
需要注意點:
1. 當需要編寫多個catch分支時,切記小類型應該放在大類型的前面
2. `catch(Exception e) {}` 作為所有異常的超類 可以捕獲所有情況
~~~
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class ExceptionTest {
public static void main(String[] args) {
// 創建一個FileInputStream類型的對象與d:/a.txt文件關聯,打開文件
FileInputStream fis = null;
try {
System.out.println("1");
// 當程序執行過程中發生了異常后直奔catch分支進行處理
fis = new FileInputStream("d:/a.txt");
System.out.println("2");
} catch (FileNotFoundException e) {
System.out.println("3");
e.printStackTrace(); // 打印報錯堆棧信息錯誤
System.out.println("4");
}
// 層層捕獲
try {
System.out.println("5");
fis.close();
System.out.println("6");
} catch (IOException e) {
System.out.println("7");
e.printStackTrace();
System.out.println("8");
} catch (NullPointerException e) {
e.printStackTrace();
}
// 一次性捕獲
try {
System.out.println("5");
fis.close();
System.out.println("6");
} catch (Exception e) {
e.printStackTrace();
}
// 不能將大捕獲寫在小捕獲前面
// try {
// System.out.println("5");
// fis.close();
// System.out.println("6");
// } /*catch (Exception e) {
// e.printStackTrace();
// }*/ catch (IOException e) {
// System.out.println("7");
// e.printStackTrace();
// System.out.println("8");
// } catch (NullPointerException e) {
// e.printStackTrace();
// } catch (Exception e) {
// e.printStackTrace();
// }
}
}
~~~
* `finally` 表示這段語句最終一定會被執行(不管有沒有拋出異常)
~~~
try {
a;
b; - 可能發生異常的語句
c;
}catch(Exception ex) {
d;
}finally {
e;
}
~~~
當**沒有發生異常**時的執行流程:**a b c e**;**當發生異常**時的執行流程:**a b d e**
~~~
public class ExceptionTest {
// 筆試考點
public static int test() {
try {
int[] arr = new int[5];
System.out.println(arr[5]);
return 0;
} catch (ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
return 1;
} finally {
return 2; // 提交結束方法并返回數據
}
}
public static void main(String[] args) {
try {
int ia = 10;
int ib = 0;
System.out.println(ia / ib);
} catch (ArithmeticException e) {
e.printStackTrace();
String str1 = null;
// str1.length(); // 會發生空指針異常
} finally {
System.out.println("無論是否發生異常都記得來執行我哦!"); // 依然是執行
}
// 如果執行了 (str1.length(); // 會發生空指針異常 )往下不執行了
System.out.println("Over!");
System.out.println("----------------------------------------");
int test = test();
System.out.println("test = " + test); // 2
}
}
~~~
>[info] ## throw 拋出異常
1. 在某些特殊情況下有些異常不能處理或者不便于處理時,就可以將該異常轉移給該方法的調用者,這種方法就叫異常的拋出。當方法執行時出現異常,則底層生成一個異常類對象拋出,此時異常代碼后續的代碼就不再執行
2. 寫法`訪問權限 返回值類型 方法名稱(形參列表) throws 異常類型1,異常類型2,...{ 方法體; }` 例如 `public void show() throws IOException{}`
>[danger] ##### 正常使用try...catch 去捕獲異常
1. 下面案例在 被調用函數內部使用 `try...catch` 捕獲,當在`show1` 和 `main` 函數調用 show 函數時候并不影響往下執行
~~~
import java.io.FileInputStream;
import java.io.IOException;
public class ThrowTest {
// 定義一個異常方法
public static void show() {
try (FileInputStream fis = new FileInputStream("D:/vscodeJava/JavaBaseTest/src/ThrowTest1.java")) {
fis.close();
} catch (IOException e) {
System.out.println("進入異常");
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void show2() {
try {
show();
} catch (Exception e) {
System.out.println("被我捕獲了么");
e.printStackTrace();
}
}
public static void main(String[] args) {
show2(); // 異常但下面執行了
System.out.println("是否執行");
}
}
~~~
* 打印結果

>[danger] ##### 在使用函數地方能過獲取異常
1. 當想讓最后使用的地方獲取異常來決定最后對異常的處理可以使用拋出異常形式
~~~
import java.io.FileInputStream;
import java.io.IOException;
public class ThrowTest {
// 定義一個異常方法
public static void show() throws IOException {
FileInputStream fis = new FileInputStream("D:/vscodeJava/JavaBaseTest/src/ThrowTest1.java");
fis.close();
}
public static void show2() throws IOException {
show();
}
// 不推薦 不建議在main方法中拋出異常 JVM負擔很重
// public static void main(String[] args) throws IOException{
// show2(); // 異常但下面執行了
// System.out.println("是否執行");
// }
public static void main(String[] args) {
show2(); // 異常
System.out.println("停止執行"); // 因為異常這類不執行了
}
// 通過捕獲執行了
// public static void main(String[] args) {
// try {
// show2();
// } catch (Exception e) {
// System.out.println("獲取異常");
// }
// // 異常但下面執行了
// System.out.println("是否執行");
// }
}
~~~
>[danger] ##### 子類重寫異常
1. 子類重寫的方法**不能拋出更大的異常、不能拋出平級不一樣的異常**,**但可以拋出一樣的異常、更小的異常以及不拋出異常**
>[info] ## 使用捕獲還是拋出異常
1. 若父類中被重寫的方法沒有拋出異常時,則子類中重寫的方法只能進行異常的捕獲處理。
2. 若一個方法內部又以遞進方式分別調用了好幾個其它方法,則建議這些方法內可以使用拋出的方法處理到最后一層進行捕獲方式處理。
>[info] ## 自定義異常
1. 除了java 官方提供的異常,也可以自定義異常類
* 自定義xxxException異常類**繼承Exception類或者其子類**
* 提供兩個版本的構造方法,一個是**無參構造方法**,另外一個是**字符串作為參數的構造方法**
~~~
public class AgeException extends Exception {
static final long serialVersionUID = 7818375828146090155L; // 序列化的版本號 與序列化操作有關系
public AgeException() {
}
public AgeException(String message) {
super(message);
}
}
~~~
* 使用
~~~
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) /*throws AgeException */{
setName(name);
setAge(age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) /*throws AgeException */{
if (age > 0 && age < 150) {
this.age = age;
} else {
//System.out.println("年齡不合理哦!!!");
try {
throw new AgeException("年齡不合理哦!!!");
} catch (AgeException e) {
e.printStackTrace();
}
}
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
~~~
- windows -- 環境變量
- Vscode -- 編寫java
- 初始java
- java -- 關鍵字
- 編寫第一個java程序
- java -- 注釋
- 計算機存儲 -- 進制
- java -- 類型
- java -- 變量
- 數字類型
- 布爾類型
- 字符類型
- 類型轉換
- 雙等比較是什么
- java -- 運算符
- 算數運算符
- 字符串拼接
- 關系/比較運算符
- 自增減運算符
- 邏輯運算符
- 三目運算
- 賦值運算符
- 移位運算符
- 位運算符
- 運算符優先級
- java -- 流程控制語句
- if /else if /if -- 判斷
- switch case分支結構
- for -- 循環
- 用雙重for循環
- while -- 循環
- do while -- 循環
- 案例練習
- java -- 數組
- 數組的存儲
- 數組的增刪改查
- 數組的特點
- 數組案例
- 二維數組
- 數組的工具方法
- java -- 方法
- java -- 方法的重載
- java -- 方法的調用流程
- java -- 類方法傳參注意事項
- java -- 方法練習案例
- 對比 return break continue
- for each循環
- java -- 基礎練習
- java -- 面向對象
- java -- 創建類和對象
- java -- 訪問控制符
- java -- 類成員方法
- java -- 構造方法
- java -- this
- java -- 封裝
- java -- 對象內存圖
- java -- 創建對象案例
- java -- static
- java -- 繼承
- super -- 關鍵字
- java -- 構造塊和靜態代碼塊
- java -- 重寫
- java -- final
- java -- 多態
- java -- 抽象類
- java -- 接口
- 引用類型數據轉換
- 綜合案例
- java -- 內部類
- java -- 回調模式
- java -- 枚舉類型
- java -- switch 使用枚舉
- java -- 枚舉方法使用
- java -- 枚舉類實現接口
- java -- javaBean
- java -- package 包
- java -- import
- java -- 遞歸練習
- java -- 設計模式
- 單例模式
- java -- 注解
- java -- 元注解
- Java -- 核心類庫
- java -- 處理字符串
- Java -- String
- String -- 常用方法
- String -- 正則
- Java -- StringBuilder 和 StringBuffer
- 知識點
- Java -- StringJoiner 字符串拼接
- 練習題
- 字符串的總結
- Java -- 包裝類
- Integer
- Double
- Boolean
- Character
- java -- 集合類
- java -- util.Collection
- Iterator接口
- java -- util.List
- java -- ArrayList
- java -- util.Queue
- java -- util.Set
- java -- util.Map
- java -- util.Collections
- Java -- Math
- Java -- java.lang
- Java -- Object
- Java -- 獲取當前時間戳
- Java -- 異常
- Java -- java.util
- java -- Date
- java -- Calender
- Java -- java.text
- Java -- SimpleDateFormat
- Java -- java.time
- Java -- java.io
- java -- io.File
- java -- 泛型
- IDEA -- 用法