Java------異常處理機制

来源:https://www.cnblogs.com/evething-begins-with-choice/archive/2020/04/03/12629123.html
-Advertisement-
Play Games

一、什麼是異常處理 異常處理從字面的意思來講就是一種發生在 java 程式中的錯誤並對其處理,但對程式員而言,異常的處理不單單的簡單去處理異常,就 ok 了,還有眾多的概念和使用異常的方式方法需要掌握 異常在 java 中分有三種: 1、編譯時異常(受檢異常) > 這種異常發生的概率很高; 2、運行 ...


一、什麼是異常處理

      異常處理從字面的意思來講就是一種發生在 java 程式中的錯誤並對其處理,但對程式員而言,異常的處理不單單的簡單去處理異常,就 ok 了,還有眾多的概念和使用異常的方式方法需要掌握

      異常在 java 中分有三種:

             1、編譯時異常(受檢異常)------> 這種異常發生的概率很高;   

             2、運行時異常 ------> 這種異常發生的概率較低,發生時直接退出 JVM;

             3、錯誤(error)-----> 錯誤和異常是不同,錯誤其實是脫離了程式員控制的問題,錯誤在代碼中經常被忽略。比如記憶體溢出,在編譯過程也是發現不了的;

 

 

       如上圖可以看出受檢異常與運行時異常都繼承於 Exception 類, 而 Exception 與 Error 繼承 Throwable 類,最終它們的父類都是 Object;

二、處理異常的方式有哪些

          處理異常的方式有兩種:

              1、throws <上拋>:在需要進行異常處理的方法體上加上 <throws  異常列表>,該方法體的異常將不會被本方法進行處理,如果誰調用該方法,則調用該方法的同時將異常一起調用。當然調用該方法的調用者可以進行處理該異常,也可以同樣使用拋出異常。

        這樣的操作其實只是將異常交給了其他的程式處理,如果其他程式沒有能力進行處理,則將一直進行拋出,直到遇見一個能夠處理該異常的程式,並終止異常(該如何處理該異常呢?);

        通過一個程式來更深次的瞭解 throws 如何處理異常:

 1  1 import java.io.FileInputStream;
 2  2 import java.io.FileNotFoundException;
 3  3 
 4  4 /**
 5  5  *  throws 的深層次理解
 6  6  */
 7  7 public class Test17 {
 8  8 
 9  9     //  public static void main(String[] args) throws FileNotFoundException{ // 當然這裡也可以直接使用父類 Exception
10 10    
11 11     public static void main(String[] args) throws Exception{
12 12 
13 13        System.out.println("我是入口");
14 14 
15 15         m1();
16 16     }
17 17 
18 18     public static void m1() throws FileNotFoundException{
19 19         // 從m1 - m3 的調用可以看出 throws 處理機制是不對異常處理,只是拋出異常,誰調用該異常,誰處理,最終會流向哪裡處理呢?
20 20 
21 21         System.out.println("m1...start!");
22 22         m2();  // m1() 也同樣出現了異常
23 23         System.out.println("m1...end!");
24 24     }
25 25 
26 26     public static void m2() throws FileNotFoundException{
27 27         //
28 28 
29 29         System.out.println("m2...start!");
30 30         m3();  // 從這個地方我們就可以看出了當 m2()進行調用 m3()時,m2() 方法體也出現需要處理的異常
31 31         // 同樣的可以依照 m3() 方法進行處理
32 32 
33 33         System.out.println("m2...end!");
34 34     }
35 35 
36 36 //  public static void m3() throws NullPointerException{
37 37         // 已經對該方法體進行了拋出異常的設置,為什麼是無效的?
38 38         // NullPointerException 因為這個是一個空指針的異常,它不對 IO 流的異常進行處理
39 39 
40 40     public static void m3() throws FileNotFoundException {
41 41         // FileNotFoundException 異常機制對 m3 起到了效果,主要因為 FileNotFoundException 繼承 IOException;
42 42 
43 43         FileInputStream fis = new FileInputStream("E:\\jaa 作業室\\temp.java");
44 44         // FileInputStream 是一個繼承了異常基本類的 IO 流; 所以同樣在使用它的時候程式員就需要對它進行處理
45 45 
46 46         System.out.println("m3...end!");
47 47     }
48 48 }
49 49 /** 看看如果讀取的路徑出現錯誤會發生什麼結果吧
50 50  * 我是入口
51 51  * m1...start!
52 52  * m2...start!
53 53  * // 這裡也出現一了一件有意思的事情:
54 54  * // 每個方法體中只有在 異常 前的值被輸出,緊跟異常之後的值直接不被讀取了
55 55  * // 從中得出一個結論: 一個方法中通過 throws 拋出的異常,在被調用時,調用者與被調用本身,異常之後的代碼將被執行中斷,不會輸出結果,異常前的值會進行輸出
56 56  *
57 57  *
58 58  * Exception in thread "main" java.io.FileNotFoundException: E:\jaa 作業室\temp.java (系統找不到指定的路徑。)
59 59  * // 這裡就是異常的處理結果了: Exception in thread "main" java.io.FileNotFoundException: E:\jaa 作業室\temp.java (系統找不到指定的路徑。)
60 60  * // 是不是發現奇妙的事情:各個方法體不斷的對異常拋出,最後在 main 方法中進行了異常處理,那為什麼方法體中就不能處理,只能在 main 中處理呢?
61 61  * // 其實 main 方法是主調方法,是一切程式的入口,方法體只有被 main 調用才能輸出結果,(當然後面還有一種方法可以在方法體中處理)而異常的處理其實
62 62  * // 也不是在 main 方法中處理的,可以看到 main 方法體上也出現了拋出異常的設置, 其實在程式員不能看到的 JVM 中,程式將異常最終交給了
63 63  * // FileNotFoundException 類處理該異常。
64 64  *
65 65  *
66 66  * at java.base/java.io.FileInputStream.open0(Native Method)
67 67  * at java.base/java.io.FileInputStream.open(FileInputStream.java:213)
68 68  * at java.base/java.io.FileInputStream.<init>(FileInputStream.java:155)
69 69  * at java.base/java.io.FileInputStream.<init>(FileInputStream.java:110)
70 70  *
71 71  * at Rview.Test17.m3(Test17.java:43)
72 72  * at Rview.Test17.m2(Test17.java:30)
73 73  * at Rview.Test17.m1(Test17.java:22)
74 74  * at Rview.Test17.main(Test17.java:15)
75 75  * // 這裡表示的是異常出現的行號索引
76 76  */
Throws 深層次理解

 

              2、try...catch... <捕捉,處理異常>: 捕捉有可能發生異常的代碼,並將它處理,不會對異常拋出,只會終止異常的向後發展

       通過一個程式來瞭解 try...catch... 如何處理異常:

 1  1 import java.io.FileInputStream;
 2  2 import java.io.FileNotFoundException;
 3  3 import java.io.FileOutputStream;
 4  4 import java.io.IOException;
 5  5 
 6  6 /**
 7  7  *  try...catch... 的使用方法和重點
 8  8  */
 9  9 
10 10 // 這是一個與 Test17 相同的程式,但我們需要對這個程式使用使用不同的異常處理機制
11 11 
12 12 public class Test18 {
13 13 
14 14     public static void main(String[] args) {
15 15 
16 16             m1();
17 17     }
18 18 
19 19         public static void m1(){
20 20 
21 21             System.out.println("m1...start!");
22 22             m2();
23 23             System.out.println("m1...end!");
24 24         }
25 25 
26 26         public static void m2(){
27 27 
28 28             System.out.println("m2...start!");
29 29             m3();
30 30             System.out.println("m2...end!");
31 31         }
32 32 
33 33 
34 34 
35 35         public static void m3(){
36 36 
37 37 
38 38         // try...catch... 的重點: 可以在發生異常點進行直接處理異常,當其他調用者調用時將不會發現該方法曾經有過異常的情況,同時也不會將異常感染
39 39         // 給調用者,總之可以直接對異常直接處理
40 40 
41 41             //  try...catch...不僅僅只能對單個異常進行捕捉處理,同時可以對多個不同類型的異常進行處理
42 42             try {
43 43                 FileInputStream fis = new FileInputStream("E:\\java\\作業室\\temp.java");
44 44                 // try 中將可能發生異常的代碼段進行捕捉
45 45                 fis.close();  // 再次出現了一個異常,再處理
46 46 
47 47                 // 以上代碼出現異常,直接進入 catch 分支,不對其後的代碼進行編譯;    
48 48                 System.out.println("hello ");
49 49             }
50 50             catch (FileNotFoundException  e/*必須要加變數名*/) {  /*將捕捉到的異常進行處理*/
51 51 
52 52                 // e.printStackTrace(); // 顯示處理結果的方法
53 53 
54 54                 System.out.println("出現了異常,已經處理!!");
55 55 
56 56             }catch (IOException e){
57 57                 // 已經進行了異常處理,為什麼出現了錯誤?
58 58                     // 兩個 catch 對不同的異常進行了處理,但是,前一個 catch 的異常處理類是最高類 Exception,而後一個 catch 的異常處理類
59 59                     // FileNotFoundException 是 Exception 的一個子類,所以在進行多次的 catch 異常處理時註意子類與父類的位置關係
60 60                     //(子類在前、父類在後  或者 同時是子類)
61 61              e.printStackTrace();
62 62             }
63 63             // 同樣要進行異常處理,這次我們將使用 try... catch... 的方式處理
64 64 
65 65             System.out.println("m3...end!");
66 66         }
67 67 }
68 68 
69 69 /** output result:
70 70  * m1...start!
71 71  * m2...start!
72 72  * m3...end!
73 73  * // 奇妙的事情又發生了,使用 try... catch...的方式處理異常並不影響異常之後的代碼運行
74 74  *
75 75  * m2...end!
76 76  * m1...end!
77 77  *
78 78  *
79 79  * java.io.FileNotFoundException: E:\java\作業室\temp.java (系統找不到指定的路徑。)
80 80  * // 這個結果的輸出靠  printStackTrace() 方法;
81 81  *
82 82  * at java.base/java.io.FileInputStream.open0(Native Method)
83 83  * at java.base/java.io.FileInputStream.open(FileInputStream.java:213)
84 84  * at java.base/java.io.FileInputStream.<init>(FileInputStream.java:155)
85 85  * at java.base/java.io.FileInputStream.<init>(FileInputStream.java:110)
86 86  *
87 87  *
88 88  * at Rview.Test18.m3(Test18.java:42)
89 89  * at Rview.Test18.m2(Test18.java:30)
90 90  * at Rview.Test18.m1(Test18.java:23)
91 91  * at Rview.Test18.main(Test18.java:17)
92 92  * // 同樣是異常出現所在的行號索引
93 93  */
try...catch 處理方式

 

三、getMessage() 和 printStackTrace()

          這是兩個都是命令行列印異常信息在程式中出錯的位置及原因,其兩者的區別在於:前者的簡單的列印出錯原因,後者是詳細的列印出錯的位置及原因,一起用一段程式瞭解一下吧

 1  1 import java.io.FileInputStream;
 2  2 import java.io.FileNotFoundException;
 3  3 
 4  4 public class Test19 {
 5  5 
 6  6     public static void main(String[] args) {
 7  7 
 8  8         m2();
 9  9     }
10 10 
11 11     public static void m2 (){
12 12         m3();
13 13     }
14 14 
15 15     public static void m3(){
16 16         try{
17 17             FileInputStream fis  = new FileInputStream("E:\\自考本科學習筆記\\英語\\基礎英語語法、English.一般現在時態.docx");
18 18 
19 19         }catch(FileNotFoundException e){
20 20             //e.printStackTrace();
21 21             /* printStackTrace(); 方法的使用 將詳細的描述錯誤的原因和錯誤出現的位置
22 22                 java.io.FileNotFoundException: E:\自考本科學習筆記\英語\基礎英語語法、English.一般現在時態.docx (系統找不到指定的文件。)
23 23                 at java.base/java.io.FileInputStream.open0(Native Method)
24 24                 at java.base/java.io.FileInputStream.open(FileInputStream.java:213)
25 25                 at java.base/java.io.FileInputStream.<init>(FileInputStream.java:155)
26 26                 at java.base/java.io.FileInputStream.<init>(FileInputStream.java:110)
27 27                 at Rview.Test19.m3(Test19.java:19)
28 28                 at Rview.Test19.m2(Test19.java:14)
29 29                 at Rview.Test19.main(Test19.java:10)*/
30 30 
31 31             String st =e.getMessage();
32 32             System.out.println(st);
33 33             /* getMessage() 方法的使用,會簡單的描述錯誤的原因
34 34             E:\自考本科學習筆記\英語\基礎英語語法、English.一般現在時態.docx (系統找不到指定的文件。)
35 35              */
36 36             
37 37          // System.out.println(e.getMessage()); 另一種寫法
38 38         }
39 39     }
40 40 }
getMessage 與 printStackTrace 使用

 

四、finally的使用

           finally 關鍵字的使用: finally 是在catch之後添加使用,它的作用是無論 try...catch...是否執行,它一定會執行

 1  1 import java.io.FileInputStream;
 2  2         import java.io.FileNotFoundException;
 3  3         import java.io.IOException;
 4  4 
 5  5 /* finally 通常在什麼情況下使用
 6  6        通常在流關閉的情況下使用,這樣可以保證關閉可以一定執行
 7  7 */
 8  8 
 9  9 public class Test20 {
10 10 
11 11     public static void main(String[] args) {
12 12         FileInputStream fis = null;
13 13         try{
14 14             fis = new FileInputStream("E:\\自考本科學習筆記\\英語\\基礎英語語法\\English.句子成分.docx");
15 15 
16 16             System.out.println("HelloWord!");
17 17             String s = null;
18 18             s.toString();
19 19 
20 20         }catch(FileNotFoundException e) {
21 21             e.printStackTrace();
22 22         } finally {
23 23             try{
24 24                 if (null != fis){
25 25                     fis.close();
26 26                 }
27 27             }catch(IOException e){
28 28                 e.printStackTrace();
29 29             }
30 30         }
31 31     }
32 32 }
finally的使用

           

           finally的面試題:

 1  1 import java.io.IOException;
 2  2 
 3  3 public class Test21 {
 4  4 
 5  5     public static void main(String[] args) {
 6  6         int result = m();
 7  7         System.out.println(result);
 8  8         // output result: 100
 9  9         /** 為什麼出現這種情況? finally 難道沒有執行嗎?
10 10          *
11 11          *  java程式有兩個亘古不變的原則: 1、 方法體中代碼必須遵循自上而下順序依次執行
12 12          *                             2、 return 語句一旦執行,整個方法必須結束
13 13          *
14 14          * */
15 15     }
16 16 
17 17     public static  int m(){
18 18         int  i = 100;
19 19         try{
20 20             return i;
21 21         } finally{
22 22             i++;
23 23         }
24 24 
25 25         /**
26 26          * 所以 該方法的底層程式執行的是這樣的程式
27 27          *    public static int m(){
28 28          *    int i = 100;
29 29          *    int j = i;
30 30          *    i ++;
31 31          *    return j;
32 32          *    }
33 33          * */
34 34     }
35 35 }
finally 的面試題

 

          細談 final、 finally、 finalize的區別

               fiinal: 修飾符(關鍵字) 如果一個類被聲明為final,意味著它不能再派生新的子類不能作為父類被繼承。因此一個類不能既被聲明為abstract,又被聲明為final的。將變數或方法聲明為final,可以保證他們使用中不被改變被聲明為final的變數必須在聲明時給定初值,而以後的引用中只能讀取,不可修改被聲明為final的方法也同樣只能使用,不能重載與 static  連用將變數變為常量;

              finally:在異常處理時提供 finally 塊來執行清楚操作。如果拋出一個異常,那麼相匹配的 catch 語句就會執行,然後控制就會進入finally塊;

              finalize:是方法名。java 技術允許使用 finalize() 方法在垃圾收集器將對象從記憶體中清除之前做必要的清理工作。這個方法是在垃圾收集器在確定了被清理對象沒有被引用的情況下調用的。finalize 是在Object 類中定義的,因此,所有的類都繼承了它。子類可以覆蓋 finalize() 方法,來整理系統資源或者執行其他清理工作。

四、運行時異常什麼時候出現

           程式在編譯階段是正常執行的,且沒有任何的錯誤,但是當運行時,就立馬出現了錯誤,並退出 JVM 這種情況在什麼時候發生呢?

          110 / 0 ---------> 這個就是一個很經典的運行時異常

 

          


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 線上應用程式升級,需要把缺失的數據關聯補充一下,你寫個程式處理一下? 客戶信息同步,由於是線上敏感欄位都是加密處理,所以需要你再寫個程式解密處理一下? 曾記得 N 年前,我經常幹這種事情,碼這種代碼。今天回過頭來,對此類事情簡單做一個分享,以防你們也遇到此類問題,不妨拿去實踐一下,說不定會提高效率呢 ...
  • 我的LeetCode:https://leetcode cn.com/u/ituring/ 我的LeetCode刷題源碼[GitHub]:https://github.com/izhoujie/Algorithmcii LeetCode 42. 接雨水 題目 給定 n 個非負整數表示每個寬度為 1 ...
  • Java概述 Java是什麼? Java is a general purpose programming language that is class based, object oriented, and designed to have as few implementation depend ...
  • 字元串常見操作 索引 切片 字元串的常見操作 應用 判斷是否是小數 ...
  • 今天不灌水,直接上乾貨!希望下麵的講解,能與你產生一些共鳴。 1. 求長度各有千秋 你是否曾經在面試的時候,經常被問到:數組有沒有 length() 方法?字元串有沒有 length() 方法? 集合有沒有 length() 方法? 面對這個問題,那麼不得不吐槽一下,Java 中獲取長度的方式,設計 ...
  • byte Byte short Short int Integer long Long boolean Boolean char Character float Float double Double 基本數據類型對象包裝類最常見作用:用於基本數據類型和字元串類型之間做轉換。 基本數據類型轉成字元串 ...
  • 我的LeetCode:https://leetcode cn.com/u/ituring/ 我的LeetCode刷題源碼[GitHub]:https://github.com/izhoujie/Algorithmcii LeetCode 36. 有效的數獨 題目 判斷一個 9x9 的數獨是否有效。只 ...
  • 時間 java8以前使用的時間很多方法都已經廢棄了,而且不是線程安全的,java8提供了一系列的時間類,這些時間類都是線程安全的 LocalDate、LocalTime、LocalDateTime 這三個關於時間的類在使用上都類似 時間戳 Duration獲取時間間隔 Peroid獲取日期間隔 Te ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...