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 Framework 4.8 開發的深度學習模型部署測試平臺,提供了YOLO框架的主流系列模型,包括YOLOv8~v9,以及其系列下的Det、Seg、Pose、Obb、Cls等應用場景,同時支持圖像與視頻檢測。模型部署引擎使用的是OpenVINO™、TensorRT、ONNX runti... ...
  • 十年沉澱,重啟開發之路 十年前,我沉浸在開發的海洋中,每日與代碼為伍,與演算法共舞。那時的我,滿懷激情,對技術的追求近乎狂熱。然而,隨著歲月的流逝,生活的忙碌逐漸占據了我的大部分時間,讓我無暇顧及技術的沉澱與積累。 十年間,我經歷了職業生涯的起伏和變遷。從初出茅廬的菜鳥到逐漸嶄露頭角的開發者,我見證了 ...
  • C# 是一種簡單、現代、面向對象和類型安全的編程語言。.NET 是由 Microsoft 創建的開發平臺,平臺包含了語言規範、工具、運行,支持開發各種應用,如Web、移動、桌面等。.NET框架有多個實現,如.NET Framework、.NET Core(及後續的.NET 5+版本),以及社區版本M... ...
  • 前言 本文介紹瞭如何使用三菱提供的MX Component插件實現對三菱PLC軟元件數據的讀寫,記錄了使用電腦模擬,模擬PLC,直至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1. PLC開發編程環境GX Works2,GX Works2下載鏈接 https:// ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • 1、jQuery介紹 jQuery是什麼 jQuery是一個快速、簡潔的JavaScript框架,是繼Prototype之後又一個優秀的JavaScript代碼庫(或JavaScript框架)。jQuery設計的宗旨是“write Less,Do More”,即倡導寫更少的代碼,做更多的事情。它封裝 ...
  • 前言 之前的文章把js引擎(aardio封裝庫) 微軟開源的js引擎(ChakraCore))寫好了,這篇文章整點js代碼來測一下bug。測試網站:https://fanyi.youdao.com/index.html#/ 逆向思路 逆向思路可以看有道翻譯js逆向(MD5加密,AES加密)附完整源碼 ...
  • 引言 現代的操作系統(Windows,Linux,Mac OS)等都可以同時打開多個軟體(任務),這些軟體在我們的感知上是同時運行的,例如我們可以一邊瀏覽網頁,一邊聽音樂。而CPU執行代碼同一時間只能執行一條,但即使我們的電腦是單核CPU也可以同時運行多個任務,如下圖所示,這是因為我們的 CPU 的 ...
  • 掌握使用Python進行文本英文統計的基本方法,並瞭解如何進一步優化和擴展這些方法,以應對更複雜的文本分析任務。 ...
  • 背景 Redis多數據源常見的場景: 分區數據處理:當數據量增長時,單個Redis實例可能無法處理所有的數據。通過使用多個Redis數據源,可以將數據分區存儲在不同的實例中,使得數據處理更加高效。 多租戶應用程式:對於多租戶應用程式,每個租戶可以擁有自己的Redis數據源,以確保數據隔離和安全性。 ...