聊聊Java中的異常及處理

来源:https://www.cnblogs.com/yychuyu/archive/2020/07/02/13226841.html
-Advertisement-
Play Games

前言 在編程中異常報錯是不可避免的。特別是在學習某個語言初期,看到異常報錯就抓耳撓腮,常常開玩笑說編程1分鐘,改bug1小時。今天就讓我們來看看什麼是異常和怎麼合理的處理異常吧! 異常與error介紹 下麵還是先讓我們來看一下基本概念吧! ​ 異常指程式運行過程中出現的非正常現象,例如用戶輸入錯誤、 ...


前言

在編程中異常報錯是不可避免的。特別是在學習某個語言初期,看到異常報錯就抓耳撓腮,常常開玩笑說編程1分鐘,改bug1小時。今天就讓我們來看看什麼是異常和怎麼合理的處理異常吧!

異常與error介紹

下麵還是先讓我們來看一下基本概念吧!

異常指程式運行過程中出現的非正常現象,例如用戶輸入錯誤、除數為零、需要處理的文件不存在、數組下標越界等。異常機制本質就是當程式出現錯誤,程式安全退出的機制。在Java的異常處理機制中,引進了很多用來描述和處理異常的類,稱為異常類。異常類定義中包含了該類異常的信息和對異常進行處理的方法。

​ Java是採用面向對象的方式來處理異常的。處理過程:

  1. 拋出異常:在執行一個方法時,如果發生異常,則這個方法生成代表該異常的一個對象,停止當前執行路徑,並把異常對象提交給JRE。
  2. 捕獲異常:JRE得到該異常後,尋找相應的代碼來處理該異常。JRE在方法的調用棧中查找,從生成異常的方法開始回溯,直到找到相應的異常處理代碼為止。

讓我們來看看前面所講到的異常類究竟是個什麼東西!

其實所有的異常對象都是派生於Throwable類的一個實例。如果內置的異常類不能夠滿足需要,還可以創建自己的異常類。所有異常的根類為java.lang.Throwable。看看它的家族長什麼樣。

Throwable類下麵主要是兩大門派。ErrorException

  • Error是程式無法處理的錯誤,表示運行應用程式中較嚴重問題,系統JVM已經處於不可恢復的崩潰狀態中。例如,說記憶體溢出和線程死鎖等系統問題。

  • Exception是程式本身能夠處理的異常。

    Exception類是所有異常類的父類,其子類對應了各種各樣可能出現的異常事件。 通常Java的異常可分為:

    1. RuntimeException 運行時異常
    2. CheckedException 已檢查異常

    下麵我們來研究研究這兩個異常。

RuntimeException和 CheckedException異同

首先我們先來看看什麼是運行時異常

這類異常通常是由編程錯誤導致的,所以在編寫程式時,並不要求必須使用異常處理機制來處理這類異常,而是經常需要通過增加“邏輯處理來避免這些異常”。

比如以下常見的幾種異常:

ArithmeticException異常

 int b=0;
 System.out.println(1/b);
 //解決:
   if(b!=0){
      System.out.println(1/b);
   }

NumberFormatException異常

String str = "1234abcf";
System.out.println(Integer.parseInt(str));
//解決: 
Pattern p = Pattern.compile("^\\d+$");
Matcher m = p.matcher(str);
if (m.matches()) { // 如果str匹配代表數字的正則表達式,才會轉換
    System.out.println(Integer.parseInt(str));
}

ClassCastException異常

Animal a=new Dog();
Cat c=(Cat)a;
//解決:    
if (a instanceof Cat) {
    Cat c = (Cat) a;
}

這裡再補充兩點,方便大家更好的理解java異常的機制和處理過程。

  1. 在方法拋出異常之後,運行時系統將轉為尋找合適的異常處理器(exception handler)。潛在的異常處理器是異常發生時依次存留在調用棧中的方法的集合。當異常處理器所能處理的異常類型與方法拋出的異常類型相符時,即為合適的異常處理器。
  2. 運行時系統從發生異常的方法開始,依次回查調用棧中的方法,直至找到含有合適異常處理器的方法並執行。當運行時系統遍歷調用棧而未找到合適的異常處理器,則運行時系統終止。同時,意味著Java程式的終止。

上面我們講述了什麼是運行時異常以及一些處理方式,下麵就再來看看什麼是已檢查異常吧!

所有不是RuntimeException的異常,統稱為Checked Exception,又被稱為“已檢查異常”,如IOException、SQLException等以及用戶自定義的Exception異常。 這類異常在編譯時就必須做出處理, 否則無法通過編譯。

通常異常的處理方式有兩種:

  1. 使用“try/catch”捕獲異常

  2. 使用“throws”聲明異常。

下麵就來詳細的聊聊吧!

異常的處理

上面已經提了,異常處理通常有2種方式。先看看捕獲異常吧。

捕獲異常是通過3個關鍵詞來實現的:try-catch-finally。用try來執行一段程式,如果出現異常,系統拋出一個異常,可以通過它的類型來捕捉(catch)並處理它,最後一步是通過finally語句為異常處理提供一個統一的出口,finally所指定的代碼都要被執行。

這個捕獲異常其實也是我們在面試的時候會經常碰到的問題。下麵我們分別再來對各個部分做一個簡單的提示吧!

  • try

一個try語句必須帶有至少一個catch語句塊或一個finally語句塊 。當異常處理的代碼執行結束以後,不會再回到try語句去執行尚未執行的代碼。

  • catch

每個try語句塊可以伴隨一個或多個catch語句,用於處理可能產生的不同類型的異常對象。在此介紹一些常用的方法,這些方法均繼承自Throwable類 。

  1. toString ()方法,顯示異常的類名和產生異常的原因。
  2. getMessage()方法,只顯示產生異常的原因,但不顯示類名。
  3. printStackTrace()方法,用來跟蹤異常事件發生時堆棧的內容。

這裡有一個需要特別註意的地方,那就是catch捕獲異常時的捕獲順序:

如果異常類之間有繼承關係,在順序安排上就需註意。越是頂層的類,越放在下麵,再不然就直接把多餘的catch省略掉。 也就是說先捕獲子類異常再捕獲父類異常。

  • finally

finally語句塊中始終都要執行,除了遇到了System.exit(0)結束程式運行。針對這個特性,所以我們通常在finally中關閉程式塊已打開的資源,比如:關閉文件流、釋放資料庫連接等。

即使try和catch塊中存在return語句,finally語句也會執行。是在執行完finally語句後再通過return退出。

在這裡就有一道非常經典的一個面試題。

public class Test {
    public static void main(String[]args) {
       System.out.println(new Test().test());;
    }
    static int test(){
       int x = 1;
       try{
          retun x;
       }finally{
          System.out.print("jdbk"+ ++x);
       }
    }
}
// 問輸出結果?

先解釋哈這裡存在的玄妙吧!

看了上面的講述,我們都知道了當try和catch中有return時,finally仍然會執行,所以正常邏輯來說此題的答案應該是“jdbk2 2”,但這裡存在一個陷阱,那就是:

finally是在return後面的表達式運算後執行的(此時並沒有返回運算後的值,而是先把要返回的值保 存起來,不管finally中的代碼怎麼樣,返回的值都不會改變,任然是之前保存的值),所以函數返回值是 在finally執行前確定的。因此正確答案應該是:“jdbk2 1”。

還有一點需要註意的就是:finally中最好不要包含return,否則程式會提前退出,返回值不是try或catch中保存的返回值。

接下來再來講講聲明異常吧,它相對來說就比較簡單了。

在一些情況下,當前方法並不需要處理髮生的異常,而是向上傳遞給調用它的方法處理。如果一個方法拋出多個已檢查異常,就必須在方法的首部列出所有的異常,之間以逗號隔開。

public static void readFile(String fileName) throws FileNotFoundException,IOException {
}

需要註意的地方就是:

  1. 在方法重寫中聲明異常時:子類重寫父類方法時,如果父類方法有聲明異常,那麼子類聲明的異常範圍不能超過父類聲明的範圍。
  2. 聲明異常我們一般在server層中。在controller層或則數據訪問層一般是捕獲異常。

自定義異常

我們為什麼要自定義異常?還不是因為在程式中,可能會遇到JDK提供的任何標準異常類都無法充分描述清楚我們想要表達的問題。此時我們就可以創建自己的異常類,即自定義異常類。

那我們怎麼自定義異常類呢?相信你看了上面的異常類的家族圖應該就猜到了。不錯,自定義異常類只需從Exception類或者它的子類派生一個子類即可。如果你繼承Exception類,則為受檢查異常,必須對其進行處理;如果不想處理,可以讓自定義異常類繼承運行時異常RuntimeException類。通常我們自定義異常類應該包含2個構造器:一個是預設的構造器,另一個是帶有詳細信息的構造器。這裡舉一個例子。

/**IllegalAgeException:非法年齡異常,繼承Exception類*/
class IllegalAgeException extends Exception {
    //預設構造器
    public IllegalAgeException() {
     
    }
    //帶有詳細信息的構造器,信息存儲在message中
    public IllegalAgeException(String message) {
        super(message);
    }
}

   public void setAge(int age) throws IllegalAgeException {
        if (age < 0) {
            throw new IllegalAgeException("人的年齡不應該為負數");
        }
        this.age = age;
    }

最後給大家講述一點使用異常機制的建議:

1.要避免使用異常處理代替錯誤處理,這樣會降低程式的清晰性,並且效率低下。

2.處理異常不可以代替簡單測試---只在異常情況下使用異常機制。

3.不要進行小粒度的異常處理---應該將整個任務包裝在一個try語句塊中。

4.異常往往在高層處理。


公眾號:良許Linux

有收穫?希望老鐵們來個三連擊,給更多的人看到這篇文章


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

-Advertisement-
Play Games
更多相關文章
  • 從業務視角還原問題、業務視角抽象問題、二次抽象發現技術問題,作為思考問題的三個還原點。 提煉單點問題解決能力、思考單點問題解決能力,複製、層層遞進思考問題,從深度和廣度出發, 深度以數據作指標,廣度以領域做方向。 腳踏實地的代碼量成長沒有捷徑。 ...
  • //前提需要 //需要一個 serialPort 工具 可在vs自帶的工具欄中獲得 //源代碼加串口工具地址: //鏈接:https://pan.baidu.com/s/1YbfvdXEmfsJX87D-Jxljyg 提取碼:d32x //記錄用戶打開的串口號 可改為泛型模式 string seri ...
  • 泥水佬大佬的地址已經不能下載,所以分享下。 用法很簡單,輸入地址即可。 鏈接:https://pan.baidu.com/s/1OUeybjqY9uGWmxe_ywgwgQ 提取碼:nls9 ...
  • 在顯示或者隱藏視窗的時候,可以利用Windows API中的AnimateWindow函數實現一些特殊的效果。主要的動畫類型有四種:滾動、幻燈片、摺疊或展開和alpha混合漸變。 ##視窗動畫效果 首先定義動畫工具類,引入AnimateWindow函數。 public class WindowsEf ...
  • 1.AMQP Messaging中的基本概念 Broker:接收和分發消息的應用,RabbitMQ Server就是Message Broker。Virtual Host:出於多租戶和安全因素設計的,把AMQP的基本組件劃分到一個虛擬的分組中,類似於網路中的Namespace概念。當多個不同的用戶使 ...
  • 1.RabbitMQ簡介 因為RabbitMQ是基於開源的AMQP協議來實現的,所以在瞭解MQ時候,首先我們來瞭解下AMQP協議。AMQP,即Advanced Message Queuing Protocol,一個提供統一消息服務的應用層標準高級消息隊列協議,是應用層協議的一個開放標準,為面向消息的 ...
  • 1. 雲停車 (開篇)2. 雲停車 (硬體篇)3. 雲停車 (業務篇)4. 雲停車 (平臺篇)5. 雲停車 (源碼篇) 網址:http://42.194.142.223:8091/Home 賬戶:admin 密碼:admin@park8888 在場記錄 出入記錄 月租車繳費記錄 臨時車繳費記錄 車場 ...
  • 通過runlike去查看一個容器的docker run啟動參數 ...
一周排行
    -Advertisement-
    Play Games
  • GoF之工廠模式 @目錄GoF之工廠模式每博一文案1. 簡單說明“23種設計模式”1.2 介紹工廠模式的三種形態1.3 簡單工廠模式(靜態工廠模式)1.3.1 簡單工廠模式的優缺點:1.4 工廠方法模式1.4.1 工廠方法模式的優缺點:1.5 抽象工廠模式1.6 抽象工廠模式的優缺點:2. 總結:3 ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 本章將和大家分享ES的數據同步方案和ES集群相關知識。廢話不多說,下麵我們直接進入主題。 一、ES數據同步 1、數據同步問題 Elasticsearch中的酒店數據來自於mysql資料庫,因此mysql數據發生改變時,Elasticsearch也必須跟著改變,這個就是Elasticsearch與my ...
  • 引言 在我們之前的文章中介紹過使用Bogus生成模擬測試數據,今天來講解一下功能更加強大自動生成測試數據的工具的庫"AutoFixture"。 什麼是AutoFixture? AutoFixture 是一個針對 .NET 的開源庫,旨在最大程度地減少單元測試中的“安排(Arrange)”階段,以提高 ...
  • 經過前面幾個部分學習,相信學過的同學已經能夠掌握 .NET Emit 這種中間語言,並能使得它來編寫一些應用,以提高程式的性能。隨著 IL 指令篇的結束,本系列也已經接近尾聲,在這接近結束的最後,會提供幾個可供直接使用的示例,以供大伙分析或使用在項目中。 ...
  • 當從不同來源導入Excel數據時,可能存在重覆的記錄。為了確保數據的準確性,通常需要刪除這些重覆的行。手動查找並刪除可能會非常耗費時間,而通過編程腳本則可以實現在短時間內處理大量數據。本文將提供一個使用C# 快速查找並刪除Excel重覆項的免費解決方案。 以下是實現步驟: 1. 首先安裝免費.NET ...
  • C++ 異常處理 C++ 異常處理機制允許程式在運行時處理錯誤或意外情況。它提供了捕獲和處理錯誤的一種結構化方式,使程式更加健壯和可靠。 異常處理的基本概念: 異常: 程式在運行時發生的錯誤或意外情況。 拋出異常: 使用 throw 關鍵字將異常傳遞給調用堆棧。 捕獲異常: 使用 try-catch ...
  • 優秀且經驗豐富的Java開發人員的特征之一是對API的廣泛瞭解,包括JDK和第三方庫。 我花了很多時間來學習API,尤其是在閱讀了Effective Java 3rd Edition之後 ,Joshua Bloch建議在Java 3rd Edition中使用現有的API進行開發,而不是為常見的東西編 ...
  • 框架 · 使用laravel框架,原因:tp的框架路由和orm沒有laravel好用 · 使用強制路由,方便介面多時,分多版本,分文件夾等操作 介面 · 介面開發註意欄位類型,欄位是int,查詢成功失敗都要返回int(對接java等強類型語言方便) · 查詢介面用GET、其他用POST 代碼 · 所 ...
  • 正文 下午找企業的人去鎮上做貸後。 車上聽同事跟那個司機對罵,火星子都快出來了。司機跟那同事更熟一些,連我在內一共就三個人,同事那一手指桑罵槐給我都聽愣了。司機也是老社會人了,馬上聽出來了,為那個無辜的企業經辦人辯護,實際上是為自己辯護。 “這個事情你不能怪企業。”“但他們總不能讓銀行的人全權負責, ...