JavaSE學習筆記(6)---異常

来源:https://www.cnblogs.com/xjtu-lyh/archive/2020/02/08/12285576.html
-Advertisement-
Play Games

JavaSE學習筆記(6) 異常 ​ 軟體程式在運行過程中,非常可能遇到問題,我們稱之為異常,英文是:Exception,意思是例外。遇到這些例外情況,或者叫異常,我們怎麼讓寫的程式做出合理的處理,安全的退出,而不至於程式崩潰呢? 1.異常產生的原因及使用原則 在 Java 中一個異常的產生,主要有 ...


JavaSE學習筆記(6)---異常

​ 軟體程式在運行過程中,非常可能遇到問題,我們稱之為異常,英文是:Exception,意思是例外。遇到這些例外情況,或者叫異常,我們怎麼讓寫的程式做出合理的處理,安全的退出,而不至於程式崩潰呢?

1.異常產生的原因及使用原則

在 Java 中一個異常的產生,主要有如下三種原因:

  1. Java 內部錯誤發生異常,Java 虛擬機產生的異常。
  2. 編寫的程式代碼中的錯誤所產生的異常,例如空指針異常、數組越界異常等。這種異常稱為未檢査的異常,一般需要在某些類中集中處理這些異常。
  3. 通過 throw 語句手動生成的異常,這種異常稱為檢査的異常,一般用來告知該方法的調用者一些必要的信息。

Java 通過面向對象的方法來處理異常。在一個方法的運行過程中,如果發生了異常,則這個方法會產生代表該異常的一個對象,並把它交給運行時的系統,運行時系統尋找相應的代碼來處理這一異常。

我們把生成異常對象,並把它提交給運行時系統的過程稱為拋出(throw)異常。運行時系統在方法的調用棧中查找,直到找到能夠處理該類型異常的對象,這一個過程稱為捕獲(catch)異常

Java 異常強制用戶考慮程式的強健性和安全性。異常處理不應用來控製程序的正常流程,其主要作用是捕獲程式在運行時發生的異常併進行相應處理。編寫代碼處理某個方法可能出現的異常,可遵循如下三個原則:

  1. 在當前方法聲明中使用 try catch 語句捕獲異常。
  2. 一個方法被覆蓋時,覆蓋它的方法必須拋出相同的異常或異常的子類。
  3. 如果父類拋出多個異常,則覆蓋方法必須拋出那些異常的一個子集,而不能拋出新異常。

2.異常的類型

在 Java 中所有異常類型都是內置類 java.lang.Throwable 類的子類,即 Throwable 位於異常類層次結構的頂層。Throwable 類下有兩個異常分支 ExceptionError,如圖所示。

img

Throwable 類是所有異常和錯誤的父類,下麵有 Error 和 Exception 兩個子類分別表示錯誤和異常。其中異常類 Exception 又分為運行時異常和非運行時異常,這兩種異常有很大的區別,也稱為不檢查異常(Unchecked Exception)和檢查異常(Checked Exception)。

  • Exception 類用於用戶程式可能出現的異常情況,它也是用來創建自定義異常類型類的類。
  • Error 定義了在通常環境下不希望被程式捕獲的異常。Error 類型的異常用於 Java 運行時由系統顯示與運行時系統本身有關的錯誤。堆棧溢出是這種錯誤的一例。
  • 本章不討論關於 Error 類型的異常處理,因為它們通常是災難性的致命錯誤,不是程式可以控制的。本章接下來的內容將討論 Exception 類型的異常處理。

運行時異常都是 RuntimeException 類及其子類異常,如 NullPointerException、IndexOutOfBoundsException 等,這些異常是不檢查異常,程式中可以選擇捕獲處理,也可以不處理。這些異常一般由程式邏輯錯誤引起,程式應該從邏輯角度儘可能避免這類異常的發生。

非運行時異常是指 RuntimeException 以外的異常,類型上都屬於 Exception 類及其子類。從程式語法角度講是必須進行處理的異常,如果不處理,程式就不能編譯通過。如 IOException、ClassNotFoundException 等以及用戶自定義的 Exception 異常,一般情況下不自定義檢查異常。下表中列出了一些常見的異常類型及它們的作用。

異常類型 說明
Exception 異常層次結構的根類
RuntimeException 運行時異常,多數 java.lang 異常的根類
ArithmeticException 算術譜誤異常,如以零做除數
ArraylndexOutOfBoundException 數組大小小於或大於實際的數組大小
NullPointerException 嘗試訪問 null 對象成員,空指針異常
ClassNotFoundException 不能載入所需的類
NumberF ormatException 數字轉化格式異常,比如字元串到 float 型數字的轉換無效
IOException I/O 異常的根類
F ileN otF oundException 找不到文件
EOFException 文件結束
InterruptedException 線程中斷
IllegalArgumentException 方法接收到非法參數
ClassCastException 類型轉換異常
SQLException 操作資料庫異常

3.異常的處理

1.捕獲異常

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

圖6-10 異常處理.png

上面過程詳細解析:

1. try:

try語句指定了一段代碼,該段代碼就是異常捕獲並處理的範圍。在執行過程中,當任意一條語句產生異常時,就會跳過該條語句中後面的代碼。代碼中可能會產生並拋出一種或幾種類型的異常對象,它後面的catch語句要分別對這些異常做相應的處理。

一個try語句必須帶有至少一個catch語句塊或一個finally語句塊 。

註意事項

當異常處理的代碼執行結束以後,不會回到try語句去執行尚未執行的代碼。

2. catch:

n-每個try語句塊可以伴隨一個或多個catch語句,用於處理可能產生的不同類型的異常對象。

n-常用方法,這些方法均繼承自Throwable類 。

​ u-toString ()方法,顯示異常的類名和產生異常的原因

​ u-getMessage()方法,只顯示產生異常的原因,但不顯示類名。

​ u-printStackTrace()方法,用來跟蹤異常事件發生時堆棧的內容。

n-catch捕獲異常時的捕獲順序:

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

2. finally:

n-有些語句,不管是否發生了異常,都必須要執行,那麼就可以把這樣的語句放到finally語句塊中。

n-通常在finally中關閉程式塊已打開的資源,比如:關閉文件流、釋放資料庫連接等。

try-catch-finally語句塊的執行過程:

try-catch-finally程式塊的執行流程以及執行結果比較複雜。

基本執行過程如下:

程式首先執行可能發生異常的try語句塊。如果try語句沒有出現異常則執行完後跳至finally語句塊執行;如果try語句出現異常,則中斷執行並根據發生的異常類型跳至相應的catch語句塊執行處理。catch語句塊可以有多個,分別捕獲不同類型的異常。catch語句塊執行完後程式會繼續執行finally語句塊。finally語句是可選的,如果有的話,則不管是否發生異常,finally語句都會被執行。

註意事項

  1. 即使try和catch塊中存在return語句,finally語句也會執行。是在執行完finally語句後再通過return退出
  2. finally語句塊只有一種情況是不會執行的,那就是在執行finally之前遇到了System.exit(0)結束程式運行

典型代碼

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class Test8 {
    public static void main(String[] args) {
        FileReader reader = null;
        try {
            reader = new FileReader("d:/a.txt");
            char c = (char) reader.read();
            char c2 = (char) reader.read();
            System.out.println("" + c + c2);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

2.拋出異常

當CheckedException產生時,不一定立刻處理它,可以再把異常throws出去。

在方法中使用try-catch-finally是由這個方法來處理異常。但是在一些情況下,當前方法並不需要處理髮生的異常,而是向上傳遞給調用它的方法處理。

如果一個方法中可能產生某種異常,但是並不能確定如何處理這種異常,則應根據異常規範在方法的首部聲明該方法可能拋出的異常。

如果一個方法拋出多個已檢查異常,就必須在方法的首部列出所有的異常,之間以逗號隔開。

註意事項

方法重寫中聲明異常原則:子類重寫父類方法時,如果父類方法有聲明異常,那麼子類聲明的異常範圍不能超過父類聲明的範圍。

典型代碼

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
 
public class Test9 {
    public static void main(String[] args) {
        try {
            readFile("joke.txt");
        } catch (FileNotFoundException e) {
            System.out.println("所需文件不存在!");
        } catch (IOException e) {
            System.out.println("文件讀寫錯誤!");
        }
    }  
    public static void readFile(String fileName) throws FileNotFoundException,          
    IOException {
        FileReader in = new FileReader(fileName);
        int tem = 0;
        try {
            tem = in.read();
            while (tem != -1) {
                System.out.print((char) tem);
                tem = in.read();
            }
        } finally {
            in.close();
        }
    }
}

4.自定義異常

  1. 在程式中,可能會遇到JDK提供的任何標準異常類都無法充分描述清楚我們想要表達的問題,這種情況下可以創建自己的異常類,即自定義異常類。

  2. 自定義異常類只需從Exception類或者它的子類派生一個子類即可。

  3. 自定義異常類如果繼承Exception類,則為受檢查異常,必須對其進行處理;如果不想處理,可以讓自定義異常類繼承運行時異常RuntimeException類。

  4. 習慣上,自定義異常類應該包含2個構造器:一個是預設的構造器,另一個是帶有詳細信息的構造器。

示例

自定義異常:

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

自定義異常的使用:

class Person {
    private String name;
    private int age;
 
    public void setName(String name) {
        this.name = name;
    }
 
    public void setAge(int age) throws IllegalAgeException {
        if (age < 0) {
            throw new IllegalAgeException("人的年齡不應該為負數");
        }
        this.age = age;
    }
 
    public String toString() {
        return "name is " + name + " and age is " + age;
    }
}
 
public class TestMyException {
    public static void main(String[] args) {
        Person p = new Person();
        try {
            p.setName("Lincoln");
            p.setAge(-1);
        } catch (IllegalAgeException e) {
            e.printStackTrace();
            System.exit(-1);
        }
        System.out.println(p);
    }
}

執行結果:

圖6-11 示例6-11運行效果圖.png

5.使用異常機制的建議

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

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

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

4.異常往往在高層處理(先瞭解!後面做項目會說!) 。


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

-Advertisement-
Play Games
更多相關文章
  • 時間限制:C/C++ 1秒,其他語言2秒 空間限制:C/C++ 256M,其他語言512M 小易給你一個包含n個數字的數組。你可以對這個數組執行任意次以下交換操作: 對於數組中的兩個下標i,j(1<=i,j<=n),如果為奇數,就可以交換和。 現在允許你使用操作次數不限,小易希望你能求出在所有能通過 ...
  • 作為開發人員,我喜歡在編碼時聽音樂。管弦樂使我可以更加專註於自己的工作。有一天,我註意到我的手指隨著音樂節奏在鍵盤上跳舞。喜歡彈鋼琴。代碼中的每個單詞或符號都和諧地書寫。然後我想...聽起來如何...我每天編寫的代碼? 這個想法誕生了。 ⭐️ 繼續在soundcode.now.sh上 直播,放置您的 ...
  • 事件的移除 removeEventListener() 第二個參數需要指定要移除的事件句柄,不能是匿名函數,因為無法識別 想要移除成功,那麼三個參數必須跟addEventListener中的三個完全一致 <!DOCTYPE html> <html lang="en"> <head> <meta ch ...
  • 前言 基於 vuex 3.1.2 按如下流程進行分析: Vue.use(Vuex) Vue.use() 會執行插件的 install 方法,並把插件放入緩存數組中。 而 Vuex 的 install 方法很簡單,保證只執行一次,以及使用 applyMixin 初始化。 applyMixin 方法定義 ...
  • input文本框中設置提示信息,可以使用placeholder屬性,結果就是這樣,有當文本框內容為空時就顯示提示信息,當輸入內容時提示內容就消失了 ...
  • 本篇文章主要來介紹什麼是數據結構。 首先讓我們來看一張圖片: 數據存儲於電腦的記憶體中。記憶體如上圖所示,形似排成 1 列的箱子,1 個箱子里存儲 1 個數據。 數據存儲於記憶體時, 決定了數據順序和位置關係的便是數據結構 。 其實在我們生活中用到很多數據結構的知識,那麼舉一個我們生活中的慄子: 首先舉 ...
  • 在瞭解完 "什麼是數據結構" 之後,讓我們一起來探索下數據結構中常見的一種— 鏈表 。 鏈表 鏈表是數據結構之一, 其中的數據呈線性排列。在鏈表中,數據的添加和刪除都較為方便,就是訪問比較耗費時間。 如上圖所示就是鏈表的概念圖,Blue、Yellow、Red 這 3 個字元串作為數據被存儲於鏈表中, ...
  • 一、數字類 1.關於數字格式化:java.text.DecimalFormat; 2.數字格式元素: # 任意數字 , 千分位 . 小數點 0 不夠補零 package com.bjpowernode.java_learning; ​ import java.text.DecimalFormat; ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...