第一章 異常1、Throwable類是java語言中的所有錯誤和異常的基類。2、 java.lang.Throwable:類是 Java 語言中所有錯誤或異常的超類。 代碼示例: 1 public class Demo01Exception {
2 public static void main(String[] args) /*throws ParseException*/ {
3 //Exception:編譯期異常,進行編譯(寫代碼)java程序出現(xiàn)的問題
4 /*SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");//用來格式化日期
5 Date date = null;
6 try {
7 date = sdf.parse("1999-0909");//把字符串格式的日期,解析為Date格式的日期
8 } catch (ParseException e) {
9 e.printStackTrace();
10 }
11 System.out.println(date);*/
12
13 //RuntimeException:運行期異常,java程序運行過程中出現(xiàn)的問題
14 /*int[] arr = {1,2,3};
15 //System.out.println(arr[0]);
16 try {
17 //可能會出現(xiàn)異常的代碼
18 System.out.println(arr[3]);
19 }catch(Exception e){
20 //異常的處理邏輯
21 System.out.println(e);
22 }*/
23
24 /*
25 Error:錯誤
26 OutOfMemoryError: Java heap space
27 內(nèi)存溢出的錯誤,創(chuàng)建的數(shù)組太大了,超出了給JVM分配的內(nèi)存
28 */
29 //int[] arr = new int[1024*1024*1024];
30 //必須修改代碼,創(chuàng)建的數(shù)組小一點
31 int[] arr = new int[1024*1024];
32 System.out.println("后續(xù)代碼");
33 }3、異常的產(chǎn)生過程解析
第二章 異常的處理Java異常處理的五個關(guān)鍵字:try、catch、finally、throw、throws 2.1 throw關(guān)鍵字 作用: 代碼示例: 1 public class Demo03Throw {
2 public static void main(String[] args) {
3 //int[] arr = null;
4 int[] arr = new int[3];
5 int e = getElement(arr,3);
6 System.out.println(e);
7 }
8 /*
9 定義一個方法,獲取數(shù)組指定索引處的元素
10 參數(shù):
11 int[] arr
12 int index
13 以后(工作中)我們首先必須對方法傳遞過來的參數(shù)進行合法性校驗
14 如果參數(shù)不合法,那么我們就必須使用拋出異常的方式,告知方法的調(diào)用者,傳遞的參數(shù)有問題
15 注意:
16 NullPointerException是一個運行期異常,我們不用處理,默認交給JVM處理
17 ArrayIndexOutOfBoundsException是一個運行期異常,我們不用處理,默認交給JVM處理
18 */
19 public static int getElement(int[] arr,int index){
20 /*
21 我們可以對傳遞過來的參數(shù)數(shù)組,進行合法性校驗
22 如果數(shù)組arr的值是null
23 那么我們就拋出空指針異常,告知方法的調(diào)用者"傳遞的數(shù)組的值是null"
24 */
25 if(arr == null){
26 throw new NullPointerException("傳遞的數(shù)組的值是null");
27 }
28
29 /*
30 我們可以對傳遞過來的參數(shù)index進行合法性校驗
31 如果index的范圍不在數(shù)組的索引范圍內(nèi)
32 那么我們就拋出數(shù)組索引越界異常,告知方法的調(diào)用者"傳遞的索引超出了數(shù)組的使用范圍"
33 */
34 if(index<0 || index>arr.length-1){
35 throw new ArrayIndexOutOfBoundsException("傳遞的索引超出了數(shù)組的使用范圍");
36 }
37
38 int ele = arr[index];
39 return ele;
40 }
41 }2.2 Objects非空判斷還記得我們學(xué)習過一個類Objects嗎,曾經(jīng)提到過它由一些靜態(tài)的實用方法組成,這些方法是null-save(空指針安全的)或null-tolerant(容忍空指針的),那么在它的源碼中,對對象為null的值進行了拋出異常操作。 Obects類中的靜態(tài)方法 public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}代碼示例: 1 public class Demo04Objects {
2 public static void main(String[] args) {
3 method(null);
4 }
5
6 public static void method(Object obj){
7 //對傳遞過來的參數(shù)進行合法性判斷,判斷是否為null
8 /*if(obj == null){
9 throw new NullPointerException("傳遞的對象的值是null");
10 }*/
11
12 //Objects.requireNonNull(obj);
13 Objects.requireNonNull(obj,"傳遞的對象的值是null");
14 }
15 }2.3 聲明異常throws 聲明異常:將問題標識出來,報告給調(diào)用者。如果方法內(nèi)通過throw拋出了編譯時異常,而沒有捕獲處理(稍后講解該方式),那么必須通過throws進行聲明,讓調(diào)用者去處理。 聲明異常格式: 修飾符 返回值類型 方法名(參數(shù)) throws 異常類名1,異常類名2…{ }throws關(guān)鍵字:處理異常的第一種方式,交給別人處理 作用: 當方法內(nèi)部拋出異常對象的時候,那么我們就必須處理這個異常對象 可以使用throws關(guān)鍵字處理異常對象,會把異常對象聲明拋出給方法的調(diào)用者處理(自己不處理,給別人處理),最終交給JVM處理 --> 中斷處理 使用格式:在方法聲明時使用 修飾符 返回值類型 方法名(參數(shù)列表) throws AAAException,BBBException...{ throws new AAAException("產(chǎn)生原因"); throws new BBBException("產(chǎn)生原因"); } 注意: 1、throws關(guān)鍵字必須寫在方法聲明處 2、throws關(guān)鍵字后邊聲明的異常必須是Exception或是Exception的子類 3、方法內(nèi)部如果拋出了多個異常對象,那么throws后邊也必須聲明多個異常 4、調(diào)用了一個聲明拋出異常的方法,我們就必須處理聲明的異常 要么繼續(xù)使用throws聲明拋出,交給方法的調(diào)用者處理,最終交給JVM 要么try...catch自己處理異常 代碼示例: 1 public class Demo05Throws {
2
3 /*
4 FileNotFoundException extends IOException extends Exception
5 如果拋出的多個異常對象有子父類關(guān)系,那么直接聲明父類即可
6 */
7 //public static void main(String[] args) throws FileNotFoundException,IOException {
8 //public static void main(String[] args) throws IOException {
9 public static void main(String[] args) throws Exception {
10 //readFile("c:\\a.txt");
11 //readFile("d:\\a.txt");
12 readFile("d:\\a.tx");
13 }
14
15 /*
16 定義一個方法,對傳遞的文件路徑進行合法性判斷
17 如果路徑不是"c:\\a.txt",那么我們就拋出文件找不到異常對象,告知方法的調(diào)用者
18 注意:
19
20 */
21
22 public static void readFile(String fileName) throws FileNotFoundException,IOException {
23 if (!fileName.equals("c:\\a.txt")){
24 throw new FileNotFoundException("傳遞的路徑不是c:\\a.txt");
25 }
26
27 /*
28 如果傳遞的路徑,不是.txt結(jié)尾
29 那么我們就拋出IO異常對象,告知方法的調(diào)用者,文件的后綴名不對
30 */
31
32 if (!fileName.endsWith(".txt")){
33 throw new IOException("文件的后綴名不對");
34 }
35 System.out.printf("路徑?jīng)]有問題,讀取文件");
36 }
37 }2.4 捕獲異常try…catch 如果異常出現(xiàn)的話,會立刻終止程序,所以我們得處理異常:
try...catch:異常處理的第二種方式,自己處理異常 } Throwable類中定義了3個異常處理的方法 包含了異常的類型,異常的原因,還包括異常出現(xiàn)的位置,在開發(fā)和調(diào)試階段,都得使用printStackTrace。 代碼示例: 1 public class Demo01TryCatch {
2 public static void main(String[] args) {
3 try{
4 //可能產(chǎn)生異常的代碼
5 readFile("d:\\a.tx");
6 System.out.println("資源釋放");
7 }catch (IOException e){//try中拋出什么異常對象,catch就定義什么異常變量,用來接收這個異常對象
8 //異常的處理邏輯,異常異常對象之后,怎么處理異常對象
9 //System.out.println("catch - 傳遞的文件后綴不是.txt");
10
11 /*
12 Throwable類中定義了3個異常處理的方法
13 String getMessage() 返回此 throwable 的簡短描述。
14 String toString() 返回此 throwable 的詳細消息字符串。
15 void printStackTrace() JVM打印異常對象,默認此方法,打印的異常信息是最全面的
16 */
17 //System.out.println(e.getMessage());//文件的后綴名不對
18 //System.out.println(e.toString());//重寫Object類的toString java.io.IOException: 文件的后綴名不對
19 //System.out.println(e);//java.io.IOException: 文件的后綴名不對
20
21 /*
22 java.io.IOException: 文件的后綴名不對
23 at com.itheima.demo02.Exception.Demo01TryCatch.readFile(Demo01TryCatch.java:55)
24 at com.itheima.demo02.Exception.Demo01TryCatch.main(Demo01TryCatch.java:27)
25 */
26 e.printStackTrace();
27 }
28 System.out.println("后續(xù)代碼");
29 }
30
31 /*
32 如果傳遞的路徑,不是.txt結(jié)尾
33 那么我們就拋出IO異常對象,告知方法的調(diào)用者,文件的后綴名不對
34
35 */
36 public static void readFile(String fileName) throws IOException {
37
38 if(!fileName.endsWith(".txt")){
39 throw new IOException("文件的后綴名不對");
40 }
41
42 System.out.println("路徑?jīng)]有問題,讀取文件");
43 }
44 }2.4 finally 代碼塊 finally:有一些特定的代碼無論異常是否發(fā)生,都需要執(zhí)行。另外,因為異常會引發(fā)程序跳轉(zhuǎn),導(dǎo)致有些語句執(zhí)行不到。而finally就是解決這個問題的,在finally代碼塊中存放的代碼都是一定會被執(zhí)行的。 finally代碼塊 }finally{ 3.當只有在try或者catch中調(diào)用退出JVM的相關(guān)方法,此時finally才不會執(zhí)行,否則finally永遠會執(zhí)行。 代碼示例: 1 public class Demo02TryCatchFinally {
2 public static void main(String[] args) {
3 try {
4 //可能會產(chǎn)生異常的代碼
5 readFile("c:\\a.tx");
6 } catch (IOException e) {
7 //異常的處理邏輯
8 e.printStackTrace();
9 } finally {
10 //無論是否出現(xiàn)異常,都會執(zhí)行
11 System.out.println("資源釋放");
12 }
13 }
14
15 /*
16 如果傳遞的路徑,不是.txt結(jié)尾
17 那么我們就拋出IO異常對象,告知方法的調(diào)用者,文件的后綴名不對
18
19 */
20 public static void readFile(String fileName) throws IOException {
21
22 if(!fileName.endsWith(".txt")){
23 throw new IOException("文件的后綴名不對");
24 }
25
26 System.out.println("路徑?jīng)]有問題,讀取文件");
27 }
28 }2.5 異常注意事項 多個異常使用捕獲又該如何處理呢? 一般我們是使用一次捕獲多次處理方式,格式如下: try{
編寫可能會出現(xiàn)異常的代碼
}catch(異常類型A e){ 當try中出現(xiàn)A類型異常,就用該catch來捕獲.
處理異常的代碼
//記錄日志/打印異常信息/繼續(xù)拋出異常
}catch(異常類型B e){ 當try中出現(xiàn)B類型異常,就用該catch來捕獲.
處理異常的代碼
//記錄日志/打印異常信息/繼續(xù)拋出異常
}注意:這種異常處理方式,要求多個catch中的異常不能相同,并且若catch中的多個異常之間有子父類異常的關(guān)系,那么子類異常要求在上面的catch處理,父類異常在下面的catch處理。
代碼示例: 1 public class Demo01Exception {
2 public static void main(String[] args) {
3 /*
4 多個異常使用捕獲又該如何處理呢?
5 1. 多個異常分別處理。
6 2. 多個異常一次捕獲,多次處理。
7 3. 多個異常一次捕獲一次處理。
8 */
9
10 //1. 多個異常分別處理。
11 /* try {
12 int[] arr = {1,2,3};
13 System.out.println(arr[3]);//ArrayIndexOutOfBoundsException: 3
14 }catch (ArrayIndexOutOfBoundsException e){
15 System.out.println(e);
16 }
17
18 try{
19 List<Integer> list = List.of(1, 2, 3);
20 System.out.println(list.get(3));//IndexOutOfBoundsException: Index 3 out-of-bounds for length 3
21 }catch (IndexOutOfBoundsException e){
22 System.out.println(e);
23 }*/
24
25 //2. 多個異常一次捕獲,多次處理。
26 /*try {
27 int[] arr = {1,2,3};
28 //System.out.println(arr[3]);//ArrayIndexOutOfBoundsException: 3
29 List<Integer> list = List.of(1, 2, 3);
30 System.out.println(list.get(3));//IndexOutOfBoundsException: Index 3 out-of-bounds for length 3
31 }catch (ArrayIndexOutOfBoundsException e){
32 System.out.println(e);
33 }catch (IndexOutOfBoundsException e){
34 System.out.println(e);
35 }*/
36
37 /*
38 一個try多個catch注意事項:
39 catch里邊定義的異常變量,如果有子父類關(guān)系,那么子類的異常變量必須寫在上邊,否則就會報錯
40 ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException
41 */
42 /*try {
43 int[] arr = {1,2,3};
44 //System.out.println(arr[3]);//ArrayIndexOutOfBoundsException: 3
45 List<Integer> list = List.of(1, 2, 3);
46 System.out.println(list.get(3));//IndexOutOfBoundsException: Index 3 out-of-bounds for length 3
47 }catch (IndexOutOfBoundsException e){
48 System.out.println(e);
49 }catch (ArrayIndexOutOfBoundsException e){
50 System.out.println(e);
51 }*/
52
53 //3. 多個異常一次捕獲一次處理。
54 /*try {
55 int[] arr = {1,2,3};
56 //System.out.println(arr[3]);//ArrayIndexOutOfBoundsException: 3
57 List<Integer> list = List.of(1, 2, 3);
58 System.out.println(list.get(3));//IndexOutOfBoundsException: Index 3 out-of-bounds for length 3
59 }catch (Exception e){
60 System.out.println(e);
61 }*/
62
63 //運行時異常被拋出可以不處理。即不捕獲也不聲明拋出。
64 //默認給虛擬機處理,終止程序,什么時候不拋出運行時異常了,在來繼續(xù)執(zhí)行程序
65 int[] arr = {1,2,3};
66 System.out.println(arr[3]);//ArrayIndexOutOfBoundsException: 3
67 List<Integer> list = List.of(1, 2, 3);
68 System.out.println(list.get(3));//IndexOutOfBoundsException: Index 3 out-of-bounds for length 3
69
70 System.out.println("后續(xù)代碼!");
71 }
72 }代碼示例: 1 /*
2 如果finally有return語句,永遠返回finally中的結(jié)果,避免該情況.
3 */
4 public class Demo02Exception {
5 public static void main(String[] args) {
6 int a = getA();
7 System.out.println(a);
8 }
9
10 //定義一個方法,返回變量a的值
11 public static int getA(){
12 int a = 10;
13 try{
14 return a;
15 }catch (Exception e){
16 System.out.println(e);
17 }finally {
18 //一定會執(zhí)行的代碼
19 a = 100;
20 return a;
21 }
22
23 }
24 }說明:調(diào)用方法后,返回值是100。為了避免永遠返回finally中的結(jié)果,finally代碼塊中盡量不要使用return語句。 子父類的異常: 代碼示例: 1 /*
2 子父類的異常:
3 - 如果父類拋出了多個異常,子類重寫父類方法時,拋出和父類相同的異?;蛘呤歉割惍惓5淖宇惢蛘卟粧伋霎惓?。
4 - 父類方法沒有拋出異常,子類重寫父類該方法時也不可拋出異常。此時子類產(chǎn)生該異常,只能捕獲處理,不能聲明拋出
5 注意:
6 父類異常時什么樣,子類異常就什么樣
7 */
8 public class Fu {
9 public void show01() throws NullPointerException,ClassCastException{}
10 public void show02() throws IndexOutOfBoundsException{}
11 public void show03() throws IndexOutOfBoundsException{}
12 public void show04() throws Exception {}
13 }
14
15 class Zi extends Fu{
16 //子類重寫父類方法時,拋出和父類相同的異常
17 public void show01() throws NullPointerException,ClassCastException{}
18 //子類重寫父類方法時,拋出父類異常的子類
19 public void show02() throws ArrayIndexOutOfBoundsException{}
20 //子類重寫父類方法時,不拋出異常
21 public void show03() {}
22
23 /*
24 父類方法沒有拋出異常,子類重寫父類該方法時也不可拋出異常。
25
26 */
27 //public void show04() throws Exception{}
28
29 //此時子類產(chǎn)生該異常,只能捕獲處理,不能聲明拋出
30 public void show04() {
31 try {
32 throw new Exception("編譯期異常");
33 } catch (Exception e) {
34 e.printStackTrace();
35 }
36 }
37 }第三章 自定義異常3.1 概述 為什么需要自定義異常類: 自定義異常類: 代碼示例: 1 /*
2 自定義異常類:
3 java提供的異常類,不夠我們使用,需要自己定義一些異常類
4 格式:
5 public class XXXExcepiton extends Exception | RuntimeException{
6 添加一個空參數(shù)的構(gòu)造方法
7 添加一個帶異常信息的構(gòu)造方法
8 }
9 注意:
10 1.自定義異常類一般都是以Exception結(jié)尾,說明該類是一個異常類
11 2.自定義異常類,必須的繼承Exception或者RuntimeException
12 繼承Exception:那么自定義的異常類就是一個編譯期異常,如果方法內(nèi)部拋出了編譯期異常,就必須處理這個異常,要么throws,要么try...catch
13 繼承RuntimeException:那么自定義的異常類就是一個運行期異常,無需處理,交給虛擬機處理(中斷處理)
14 */
15 public class RegisterException extends /*Exception*/ RuntimeException{
16 //添加一個空參數(shù)的構(gòu)造方法
17 public RegisterException(){
18 super();
19 }
20
21 /*
22 添加一個帶異常信息的構(gòu)造方法
23 查看源碼發(fā)現(xiàn),所有的異常類都會有一個帶異常信息的構(gòu)造方法,方法內(nèi)部會調(diào)用父類帶異常信息的構(gòu)造方法,讓父類來處理這個異常信息
24 */
25 public RegisterException(String message){
26 super(message);
27 }
28 }3.2 自定義異常的練習要求:我們模擬注冊操作,如果用戶名已存在,則拋出異常并提示:親,該用戶名已經(jīng)被注冊。 Demo01RegisterException.java: 1 import java.util.Scanner;
2
3 /*
4 要求:我們模擬注冊操作,如果用戶名已存在,則拋出異常并提示:親,該用戶名已經(jīng)被注冊。
5
6 分析:
7 1.使用數(shù)組保存已經(jīng)注冊過的用戶名(數(shù)據(jù)庫)
8 2.使用Scanner獲取用戶輸入的注冊的用戶名(前端,頁面)
9 3.定義一個方法,對用戶輸入的中注冊的用戶名進行判斷
10 遍歷存儲已經(jīng)注冊過用戶名的數(shù)組,獲取每一個用戶名
11 使用獲取到的用戶名和用戶輸入的用戶名比較
12 true:
13 用戶名已經(jīng)存在,拋出RegisterException異常,告知用戶"親,該用戶名已經(jīng)被注冊";
14 false:
15 繼續(xù)遍歷比較
16 如果循環(huán)結(jié)束了,還沒有找到重復(fù)的用戶名,提示用戶"恭喜您,注冊成功!";
17 */
18 public class Demo01RegisterException {
19 // 1.使用數(shù)組保存已經(jīng)注冊過的用戶名(數(shù)據(jù)庫)
20 static String[] usernames = {"張三","李四","王五"};
21
22 public static void main(String[] args) /*throws RegisterException*/ {
23 //2.使用Scanner獲取用戶輸入的注冊的用戶名(前端,頁面)
24 Scanner sc = new Scanner(System.in);
25 System.out.println("請輸入您要注冊的用戶名:");
26 String username = sc.next();
27 checkUsername(username);
28
29 }
30
31 //3.定義一個方法,對用戶輸入的中注冊的用戶名進行判斷
32 public static void checkUsername(String username) /*throws RegisterException*/ {
33 //遍歷存儲已經(jīng)注冊過用戶名的數(shù)組,獲取每一個用戶名
34 for (String name : usernames) {
35 //使用獲取到的用戶名和用戶輸入的用戶名比較
36 if(name.equals(username)){
37 //true:用戶名已經(jīng)存在,拋出RegisterException異常,告知用戶"親,該用戶名已經(jīng)被注冊";
38 try {
39 throw new RegisterException("親,該用戶名已經(jīng)被注冊");
40 } catch (RegisterException e) {
41 e.printStackTrace();
42 return; //結(jié)束方法(否則會執(zhí)行下面的System.out.println("恭喜您,注冊成功!");語句)
43 }
44 }
45 }
46 //如果循環(huán)結(jié)束了,還沒有找到重復(fù)的用戶名,提示用戶"恭喜您,注冊成功!";
47 System.out.println("恭喜您,注冊成功!");
48 }
49 }Demo02RegisterException.java: 1 import java.util.Scanner;
2
3 /*
4 要求:我們模擬注冊操作,如果用戶名已存在,則拋出異常并提示:親,該用戶名已經(jīng)被注冊。
5
6 分析:
7 1.使用數(shù)組保存已經(jīng)注冊過的用戶名(數(shù)據(jù)庫)
8 2.使用Scanner獲取用戶輸入的注冊的用戶名(前端,頁面)
9 3.定義一個方法,對用戶輸入的中注冊的用戶名進行判斷
10 遍歷存儲已經(jīng)注冊過用戶名的數(shù)組,獲取每一個用戶名
11 使用獲取到的用戶名和用戶輸入的用戶名比較
12 true:
13 用戶名已經(jīng)存在,拋出RegisterException異常,告知用戶"親,該用戶名已經(jīng)被注冊";
14 false:
15 繼續(xù)遍歷比較
16 如果循環(huán)結(jié)束了,還沒有找到重復(fù)的用戶名,提示用戶"恭喜您,注冊成功!";
17 */
18 public class Demo02RegisterException {
19 // 1.使用數(shù)組保存已經(jīng)注冊過的用戶名(數(shù)據(jù)庫)
20 static String[] usernames = {"張三","李四","王五"};
21
22 public static void main(String[] args) {
23 //2.使用Scanner獲取用戶輸入的注冊的用戶名(前端,頁面)
24 Scanner sc = new Scanner(System.in);
25 System.out.println("請輸入您要注冊的用戶名:");
26 String username = sc.next();
27 checkUsername(username);
28
29 }
30
31 //3.定義一個方法,對用戶輸入的中注冊的用戶名進行判斷
32 public static void checkUsername(String username) {
33 //遍歷存儲已經(jīng)注冊過用戶名的數(shù)組,獲取每一個用戶名
34 for (String name : usernames) {
35 //使用獲取到的用戶名和用戶輸入的用戶名比較
36 if(name.equals(username)){
37 //true:用戶名已經(jīng)存在,拋出RegisterException異常,告知用戶"親,該用戶名已經(jīng)被注冊";
38 throw new RegisterException("親,該用戶名已經(jīng)被注冊");//拋出運行期異常,無需處理,交給JVM處理,中斷處理
39 }
40 }
41
42 //如果循環(huán)結(jié)束了,還沒有找到重復(fù)的用戶名,提示用戶"恭喜您,注冊成功!";
43 System.out.println("恭喜您,注冊成功!");
44 }
45 }
|
|
|