Java學習筆記(十三)面向對象---異常

来源:https://www.cnblogs.com/liyuxin2/archive/2020/02/28/12380483.html
-Advertisement-
Play Games

概述 對異常的理解 程式在運行過程中出現不正常情況。是對問題的描述,將問題進行對象的封裝。 異常的由來 問題也是現實生活中一個具體的事物,也可以通過Java的類的形式進行描述,並封裝成對象。 對於問題的劃分 一種是嚴重的問題,一種是非嚴重的問題。 + 對於嚴重的:Java通過Error類進行描述。 ...


概述

對異常的理解

程式在運行過程中出現不正常情況。是對問題的描述,將問題進行對象的封裝。

異常的由來

問題也是現實生活中一個具體的事物,也可以通過Java的類的形式進行描述,並封裝成對象。

對於問題的劃分

一種是嚴重的問題,一種是非嚴重的問題。

  • 對於嚴重的:Java通過Error類進行描述。
    對於Error一般不編寫針對性的代碼對其進行處理。
  • 對於非嚴重的:Java通過Exception類進行描述。
    對於Exception可以使用針對性的處理方式進行處理。
    無論Error還是Exception都具有一些共性內容。
    比如:不正常情況的信息,引發原因。

    異常體系

    Throwable
        |--Error
        |--Exception
            |--RuntimeException

異常體系的特點:
異常體系中的所有類以及被建立的對象都具備可拋性。

異常的處理

代碼語句格式

try {
    需要被檢測的代碼
}
catch(異常類 變數) {
    處理異常的代碼(處理方式)
}
finally {
    一定會執行的語句;
}

對異常的常見操作方法

String getMessage();
String toString();
void printStackTrace();

class Demo {
    int div(int x,int y) {
        return x/y;
    }
}
public class ExceptionDemo {
    public static void main(String[] args) {
        Demo d = new Demo();
        try {
            int z = d.div(1,0);
            System.out.println(z);
        }
        catch (Exception e) {  //Exception e = new ArithmeticExceptin();
            System.out.println(e.getMessage()); //  /by zero
            System.out.println(e.toString());   //  異常名稱:異常信息
            e.printStackTrace();                //  異常名稱:異常信息,異常出現的位置
            //(jvm預設的處理異常的機制就是在調用printStackTrace()方法)
        }
        System.out.println("over");
    }
}

運行結果

/ by zero
java.lang.ArithmeticException: / by zero
java.lang.ArithmeticException: / by zero
    at Demo.div(ExceptionDemo.java:3)
    at ExceptionDemo.main(ExceptionDemo.java:10)
over

異常聲明throws

  • throws關鍵字用來聲明一個方法有可能會出現問題。
  • throws關鍵字可以將異常拋給調用者,可以層層向上拋,直到最後由Java虛擬機拋出。
    比如:
class Demo {
    int div(int x,int y) throws Exception {
        return x/y;
    }
}
public class ExceptionDemo1 {
    public static void main(String[] args) throws Exception {
        Demo d = new Demo();
        int y = d.div(1,0);
        System.out.println(y);
        System.out.println("over");
    }
}
  • 如果調用者對被調用方法拋出的異常不加處理會出現編譯錯誤。
class Demo {
    int div(int x,int y) throws Exception {
        return x/y;
    }
}
public class ExceptionDemo2 {
    public static void main(String[] args) {
        Demo d = new Demo();
        int y = d.div(1,0);
        System.out.println(y);
        System.out.println("over");
    }
}

上述代碼編譯會提示:

Error:(9, 22) java: 未報告的異常錯誤java.lang.Exception; 必須對其進行捕獲或聲明以便拋出

我們對可能出現的異常加以處理:

class Demo {
    int div(int x,int y) throws Exception {
        return x/y;
    }
}
public class ExceptionDemo3 {
    public static void main(String[] args) {
        Demo d = new Demo();
        try {
            int y = d.div(1,0);
            System.out.println(y);
        }
        catch (Exception e) {
            System.out.println(e.toString());
        }
        System.out.println("over");
    }
}

運行結果:

java.lang.ArithmeticException: / by zero
over

對可能出現異常的div方法進行處理之後,程式可以正常編譯運行。

多異常處理

1.聲明異常時,聲明為更為具體的異常,這樣可以處理得更具體。
2.方法聲明有幾個異常,對應就有幾個catch塊。(不要定義多餘的catch塊)
如果多個catch塊中的異常出現繼承關係,父類異常catch塊放在最下麵。

class Demo {
    int div(int x,int y) throws ArithmeticException,ArrayIndexOutOfBoundsException {
        int[] arr = new int[x];
        System.out.println(arr[3]);
        return x/y;
    }
}
public class ExceptionDemo4 {
    public static void main(String[] args) {
        Demo d = new Demo();
        try {
            int y = d.div(2,0);
        }
        catch (ArithmeticException e) {
            System.out.println("被零除了");
        }
        catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("數組角標越界");
        }
    }
}

運行結果:

數組角標越界

上述代碼中顯然有兩個一場出現,但是當方法中出現一個異常之後方法會停止運行,不會繼續執行下去。

自定義異常

項目中會出現特有的問題,而這些問題並未被Java描述並封裝對象。所以對這些特有的問題可以按照Java的對問題封裝的思想,將特有的問題,進行自定義的異常封裝。

需求:在本程式中,對於除數是負數,也視為是錯誤的。
當在函數內部出現了throw拋出異常對象,那麼就必須要給對應的處理。
要麼在內部使用try catch處理。
要麼在函數上聲明讓調用者處理。

class FuShuException extends Exception {

}
class Demo {
    int div(int x,int y) throws FuShuException{
        if(y<0) {
            throw new FuShuException();//通過throw關鍵字手動拋出一個自定義異常對象
        }
        return x/y;
    }
}
public class ExceptionDemo5 {
    public static void main(String[] args) {
        Demo d = new Demo();
        try {
            int y = d.div(1,-1);
            System.out.println(y);
        }
        catch (FuShuException e) {
            System.out.println(e.toString());
            System.out.println("除數出現負數了");
        }
    }
}

運行結果

FuShuException
除數出現負數了

我們可以發現以上的代碼運行的結果中只有異常的名稱,卻沒有異常的信息。因為我們並未在自定義的異常中定義具體信息。

定義異常信息

因為父類中已經把異常信息的操作完成了。所以子類只要在構造時,將異常信息傳遞給父類通過super語句,就可以通過getMessage方法獲取自定義的異常信息。

class FuShuException extends Exception {
    private int value;
    FuShuException(){
        super();
    }
    FuShuException(String message,int value) {
        super(message);
        this.value = value;
    }
    public int getValue() {
        return value;
    }
}
class Demo {
    int div(int x,int y) throws FuShuException{
        if(y<0) {
            throw new FuShuException("--被零除了--",y);//通過throw關鍵字手動拋出一個自定義異常對象
        }
        return x/y;
    }
}
public class ExceptionDemo5 {
    public static void main(String[] args) {
        Demo d = new Demo();
        try {
            int y = d.div(1,-1);
            System.out.println(y);
        }
        catch (FuShuException e) {
            System.out.println(e.toString());
            System.out.println("除數出現了負數:"+e.getValue());
        }
    }
}

運行結果:

FuShuException: --被零除了--
除數出現了負數:-1

註意

自定義異常必須是是自定義類繼承Exception
異常體系中的異常類和異常對象都具備可拋性,這個可拋性是Throwable這個體系中獨有的特點。只有這個體系中的類和對象才可以被throw和throws操作。

throw和throws的區別

  1. throws使用在函數上,throw使用在函數內。
  2. throws後面跟的是異常類,可以跟多個用逗號隔開。throw後跟的是異常對象。

RuntimeException

異常分兩種

  1. 編譯時被檢測的異常。
  2. 編譯時不被檢測的異常(運行時的異常。RuntimeException以及其子類)

RuntimeException是Exception中的一個特殊的子類。
如果在函數內容中拋出異常,函數上可以不用聲明。
如果在函數上聲明瞭異常,調用者可以不用進行處理。

之所以不用在函數上聲明是因為不需要讓調用者處理,當該異常發生,程式希望停止,對代碼進行修正,而不是去讓調用者處理。

自定義異常時,如果該異常發生,無法再繼續進行運算,就讓自定義異常繼承RuntimeException。

class FuShuException extends RuntimeException{
    FuShuException(String message) {
        super(message);
    }
}
class Demo {
        int div(int x,int y) {  //函數上為聲明異常也可以正常編譯
            if (y < 0) {
                throw new FuShuException("--除數為負數--");//在函數內容中拋出異常
            }
            else if(y == 0){
                throw new ArithmeticException("--除數為零--");//在函數內容中拋出異常
            }
            return x/y;
        }
}
public class ExceptionDemo6 {
    public static void main(String[] args) {
        Demo d = new Demo();
        try {
            int y = d.div(1,-1);
        }
        catch (FuShuException e) {
            System.out.println(e.toString());
        }
        catch (ArithmeticException e) {
            System.out.println(e.toString());
        }
    }
}

finally

try {

}
catch () {

}
finally {

}

finally中存放的是一定會被執行(無論是否有異常)的代碼,即使catch中有return語句。

finally只有一種情況不會被執行,當代碼執行到System.exit(0);

例如:如果需要對資料庫進行操作,無論有沒有成功連接上資料庫,在最後操作完成的時候,都需要斷開資料庫的連接,以釋放有限的資源。

異常處理語句的另一種格式

try {
    
}
finally {

}

異常在覆蓋時的特點

  1. 子類在覆蓋父類時,如果父類的方法拋出異常,那麼子類的覆蓋方法只能拋出父類的異常或者該異常的子類。子類程式在繼承時不能拋出新的異常。
  2. 如果父類方法拋出多個異常,那麼子類在覆蓋方法時,只能拋出父類異常的子集。
  3. 如果父類或者介面的方法中沒有異常拋出,那麼子類在覆蓋方法時,也不可以拋出異常如果子類方法發生了異常,就必須要進行try處理,不可以拋出。

異常的好處

  1. 將問題進行封裝。
  2. 將正常流程代碼和問題處理代碼相分離,增強代碼可讀性。

    異常的處理原則

  3. 兩種處理方式: try和throws
  4. 調用到拋出異常的功能時,拋出幾個,就需要處理幾個。一個try對應多個catch
  5. 多個catch需要將父類異常的catch放到最下麵。
  6. catch內,需要定義針對性處理方式,不要簡單地定義printStackTrace。
    • 當捕獲到地異常,無法處理,可以繼續在catch中拋出該無法處理的異常
    • 如果該異常處理不了,但並不屬於該功能出現的異常,可以將該異常進行轉換然後再拋出
    • 如果異常可以處理,但需要使拋出的異常和本功能相關,也可以對異常進行轉換

異常練習

有圓形和長方形,都可以獲取面積,對於面積,如果出現非法的數值,視為是獲取面積出現問題。
出現的問題通過異常來表示。(使用異常可以,使問題處理代碼和正常流程代碼分開)

interface Shape {
    void getArea();
}
class InvaidValueException extends RuntimeException {//如果一個傳入一個圖形的參數有錯誤,我們無法對其進行有效的處理,只拋出異常即可,所以繼承RuntimeException
    InvaidValueException(String message) {
        super(message);
    }
}
class Rec implements Shape {
    private double len,wid;
    Rec(double len,double wid) {
        if(len <= 0 || wid <= 0)
                throw new InvaidValueException("非法值");
        this.len = len;
        this.wid = wid;
    }
    @Override
    public void getArea() {
        System.out.println(wid*len);
    }
}

class Circle implements Shape {
    private double r;
    public static final double PI = 3.14;
    Circle(double r)  {
        if(r <= 0)
            throw new InvaidValueException("非法值");
        this.r = r;
    }
    @Override
    public void getArea() {
        System.out.println(r*r*PI);
    }
}
public class ExceptionDemo7 {
    public static void main(String[] args) {
        Rec R = new Rec(1,2);
        R.getArea();
        Circle C = new Circle(-1);
        C.getArea();
        System.out.println("over");
    }
}

上述程式的運行結果為:

2.0
Exception in thread "main" InvaidValueException: 非法值
    at Circle.<init>(ExceptionDemo7.java:28)
    at ExceptionDemo7.main(ExceptionDemo7.java:41)

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

-Advertisement-
Play Games
更多相關文章
  • python3-cookbook中每個小節以問題、解決方案和討論三個部分探討了Python3在某類問題中的最優解決方式,或者說是探討Python3本身的數據結構、函數、類等特性在某類問題上如何更好地使用。這本書對於加深Python3的理解和提升Python編程能力的都有顯著幫助,特別是對怎麼提高Py ...
  • 一、 1.讓SortedSet集合做到排序還有另一種方式:java.util.Comparator; 2.單獨編寫一個比較器 package com.bjpowernode.java_learning; import java.util.*; ​ public class D90_1_SortedS ...
  • 明確學習目標,不急於求成 當下是一個喧囂、浮躁的時代。我們總是被生活中大量涌現的熱點所吸引,幾乎沒有深度閱讀和思考的時間和機會。我始終認為,學習是需要沉下心來慢慢鑽研的,是長 期的;同時,學習不應該被賦予太多的功利色彩。一個Python 程式員的成長路線圖應該是這樣子的:基礎語法–>語感訓練–>課題 ...
  • python3-cookbook中每個小節以問題、解決方案和討論三個部分探討了Python3在某類問題中的最優解決方式,或者說是探討Python3本身的數據結構、函數、類等特性在某類問題上如何更好地使用。這本書對於加深Python3的理解和提升Python編程能力的都有顯著幫助,特別是對怎麼提高Py ...
  • 基於JSP+Servlet開發超市日常管理系統: 開發環境: Windows操作系統開發工具: Eclipse+Jdk+Tomcat+MYSQL資料庫題目:根據超市日常所做的工作描述,結合超市經理提出的超市管理需求,本超市管理系統主要提供以下功能:超市經理能夠進行商品的添加、商品的查看,商品的信息修 ...
  • 基於JSP+Servlet開發學生成績管理系統 開發環境: Windows操作系統開發工具: MyEclipse+Jdk+Tomcat+Mysql資料庫運行效果圖 源碼及原文鏈接:https://javadao.xyz/forum.php?mod=viewthread&tid=57 ...
  • 異常處理涉及的關鍵字: try: 理解它是掃描器,將可能出現異常的代碼放入其中; 如果在執行的過程中出現異常對象了,掃描器會立即察覺到此異常對象, 但是它沒有處理它的能力,所以會將異常對象給到except(捕獲器)進行處理 except: 理解它是捕獲器,後面可以定義異常類型,並且和as關鍵字配合使 ...
  • swap(a,b) 用於交換a,b兩個變數的值; template void swap ( T& a, T& b ) { T c(a); a=b; b=c; } reverse() reverse函數反轉區間的數據 sort() sort函數對區間的函數進行排序,內部是實現使用快速排序法。 max( ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...