欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java 知識難點之異常的認知與使用詳解

 更新時間:2021年09月26日 09:53:42   作者:意愿三七  
所謂異常是指程序在運行時出現(xiàn)錯誤時提示調(diào)用者的機制,異常的種類有很多,不同種類的異常有不同的含義,也有不同的處理方式,通讀本篇對大家的學習或工作具有一定的價值,需要的朋友可以參考下

前言

本篇文章你會學習到什么是異常,異常的基本語法使用,和自定義異常,干貨多多?。。?/p>

在這里插入圖片描述

一、 異常的背景

初識異常

我們曾經(jīng)的代碼中已經(jīng)接觸了一些 “異?!?了. 例如

除以 0

public static void main(String[] args) {
        System.out.println(10 / 0);
    }

算術異常:

在這里插入圖片描述

數(shù)組下標越界

數(shù)組越界

int[] arr = {1, 2, 3};
System.out.println(arr[100]);
// 執(zhí)行結果
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 100

訪問 null 對象

空指針異常

public class Test {
    public int num = 10;
    public static void main(String[] args) {
        Test t = null;
        System.out.println(t.num);
   }
}
// 執(zhí)行結果
Exception in thread "main" java.lang.NullPointerException

異常分為2種:

運行時異常(非受查異常)

  • 算數(shù)異常 數(shù)組越界異常 空指針異常 都是程序運行的過程當中發(fā)生的異常

編譯時異常(受查異常)

  • 比如使用clone方法 在編譯前就劃紅線了就是編譯時異常

在這里插入圖片描述

異常體系:

在這里插入圖片描述

我們來看一下空指針異常(其實是一個類繼承了運行時異常)

在這里插入圖片描述

對應上面的圖,

在看一下運行時異常:繼承了Exception(也可以看上面的圖)

在這里插入圖片描述

看一下Exception 繼承了Throwable:

在這里插入圖片描述

通過這個圖我們得到一個結論:每一個異常都是一個類,異常之間的關系 參考圖上繼承

我們看看Error

在這里插入圖片描述

這個就叫做錯誤

在這里插入圖片描述

異常和錯誤的區(qū)別:

錯誤:必須由程序員處理邏輯錯誤
異常:處理異常就OK了接下來繼續(xù)看

防御式編程:

錯誤在代碼中是客觀存在的. 因此我們要讓程序出現(xiàn)問題的時候及時通知程序猿. 我們有兩種主要的方式
LBYL: Look Before You Leap. 在操作之前就做充分的檢查.

EAFP: It's Easier to Ask Forgiveness than Permission. “事后獲取原諒比事前獲取許可更容易”. 也就是先操作, 遇到問題再處理.

注意!!! 上面這兩個概念千萬不要背!
其實很好理解, 舉個栗子~~
比如老濕年輕的時候, 和你們師娘剛開始談對象. 我們都知道, 談對象需要有一些親密的動作, 比如 “拉小手” 這 種. emmmmm 問題來了, 老濕去拉師娘的小手有兩種方式:

a) 老濕說, 妹子, 我拉你小手可以嘛? 獲取妹子的同意后, 再拉手(這就是 LBYL).

b) 老濕趁妹子不備, 直接拉住. 大不了妹子生氣了給老濕一巴掌, 老濕再道歉就是(這就是 EAFP).

異常的核心思想就是 EAFP.

異常的好處

例如, 我們用偽代碼演示一下開始一局王者榮耀的過程.

LBYL 風格的代碼(不使用異常)

boolean ret = false;
ret = 登陸游戲();
if (!ret) {
 處理登陸游戲錯誤;
    return; }
ret = 開始匹配();
if (!ret) {
 處理匹配錯誤;
    return; }
ret = 游戲確認();
if (!ret) {
 處理游戲確認錯誤;
    return; }
ret = 選擇英雄();
if (!ret) {
    處理選擇英雄錯誤;
    return; }
ret = 載入游戲畫面();
if (!ret) {
 處理載入游戲錯誤;
    return; }

EAFP 風格的代碼(使用異常)

try {
    登陸游戲();
    開始匹配();
    游戲確認();
    選擇英雄();
    載入游戲畫面();
   ...
} catch (登陸游戲異常) {
    處理登陸游戲異常;
} catch (開始匹配異常) {
 處理開始匹配異常;
} catch (游戲確認異常) {
 處理游戲確認異常;
} catch (選擇英雄異常) {
 處理選擇英雄異常;
} catch (載入游戲畫面異常) {
 處理載入游戲畫面異常; }

對比兩種不同風格的代碼, 我們可以發(fā)現(xiàn), 使用第一種方式, 正常流程和錯誤處理流程代碼混在一起, 代碼整體顯的比較混亂. 而第二種方式正常流程和錯誤流程是分離開的, 更容易理解代碼

二、異常的基本用法

基本語法

在這里插入圖片描述

  • try 代碼塊中放的是可能出現(xiàn)異常的代碼.
  • catch 代碼塊中放的是出現(xiàn)異常后的處理行為.
  • finally 代碼塊中的代碼用于處理善后工作, 會在最后執(zhí)行.
  • 其中 catch 和 finally 都可以根據(jù)情況選擇加或者不加.

代碼:

public static void main(String[] args) {
        int[] arr = {1, 2, 3};
        System.out.println("before");
        System.out.println(arr[100]);
        System.out.println("after");
    }

在這里插入圖片描述

解釋:

在這里插入圖片描述

我們發(fā)現(xiàn)一旦出現(xiàn)異常, 程序就終止了. after 沒有正確輸出

為什么?

當沒有處理異常的時候一旦程序發(fā)生了異常之后,這個異常會交給jvm,如果給jvm處理異常,那么程序一定會終止。

我們來自己處理異常:catch一定要捕獲相應的異常(沒有捕獲到就交給了JVM了)

在這里插入圖片描述

結果:

在這里插入圖片描述

但是下面的也不會執(zhí)行了

在這里插入圖片描述

相比上面的我們處理了異常,讓程序可以繼續(xù)運行下去了

那上面是沒有異常消息的提示了,我們還想要些提示怎么搞呢??

使用:e.printStackTrace(); after還是正常出來

在這里插入圖片描述

這個紅字可以進行參考。

代碼示例 catch 可以有多個:

在這里插入圖片描述

一段代碼可能會拋出多種不同的異常, 不同的異常有不同的處理方式. 因此可以搭配多個 catch 代碼塊.
如果多個異常的處理方式是完全相同, 也可以寫成這樣

代碼示例 也可以用一個 catch 捕獲所有異常(不推薦)

int[] arr = {1, 2, 3};
try {
    System.out.println("before");
    arr = null;
    System.out.println(arr[100]);
    System.out.println("after");
} catch (Exception e) {
    e.printStackTrace();
}
System.out.println("after try catch");

為什么不推薦了,因為exception 范圍太大了,不好排查

代碼示例 finally 的執(zhí)行不需要條件

int[] arr = {1, 2, 3};
try {
    System.out.println("before");
    arr = null;
    System.out.println(arr[100]);
    System.out.println("after");
} catch (Exception e) {
    e.printStackTrace();
} finally {
    System.out.println("finally code");
}

在這里插入圖片描述

finally 無論有沒有異常都會最后執(zhí)行

代碼示例 使用 try 負責回收資源

Scanner.close()可以釋放資源可以寫到finally里面,也可以直接寫到try里面

try (Scanner sc = new Scanner(System.in)) {
    int num = sc.nextInt();
    System.out.println("num = " + num);
} catch (Exception e) {
    e.printStackTrace();
}

代碼示例 如果向上一直傳遞都沒有合適的方法處理異常, 最終就會交給 JVM 處理, 程序就會異常終止(和我們最開始未使用 try catch 時是一樣的).

public static void main(String[] args) {
    try {
        func();
   } catch (ArrayIndexOutOfBoundsException e) {
        e.printStackTrace();
   }
    System.out.println("after try catch");
}
public static void func() {
    int[] arr = {1, 2, 3};
    System.out.println(arr[100]);
}
// 直接結果
java.lang.ArrayIndexOutOfBoundsException: 100
 at demo02.Test.func(Test.java:18)
 at demo02.Test.main(Test.java:9)
after try catch

可以看見上面代碼是func可以有異常,但是在main方法里面處理了的

異常處理流程

  • 程序先執(zhí)行 try 中的代碼
  • 如果 try 中的代碼出現(xiàn)異常, 就會結束 try 中的代碼, 看和 catch 中的異常類型是否匹配.
  • 如果找到匹配的異常類型, 就會執(zhí)行 catch 中的代碼
  • 如果沒有找到匹配的異常類型, 就會將異常向上傳遞到上層調(diào)用者.
  • 無論是否找到匹配的異常類型, finally 中的代碼都會被執(zhí)行到(在該方法結束之前執(zhí)行).
  • 如果上層調(diào)用者也沒有處理的了異常, 就繼續(xù)向上傳遞.
  • 一直到 main 方法也沒有合適的代碼處理異常, 就會交給 JVM 來進行處理, 此時程序就會異常終止.

關于異常的處理方式

異常的種類有很多, 我們要根據(jù)不同的業(yè)務場景來決定.

對于比較嚴重的問題(例如和算錢相關的場景), 應該讓程序直接崩潰, 防止造成更嚴重的后果

對于不太嚴重的問題(大多數(shù)場景), 可以記錄錯誤日志, 并通過監(jiān)控報警程序及時通知程序猿

對于可能會恢復的問題(和網(wǎng)絡相關的場景), 可以嘗試進行重試.

在我們當前的代碼中采取的是經(jīng)過簡化的第二種方式. 我們記錄的錯誤日志是出現(xiàn)異常的方法調(diào)用信息, 能很快

速的讓我們找到出現(xiàn)異常的位置. 以后在實際工作中我們會采取更完備的方式來記錄異常信息

拋出異常

除了 Java 內(nèi)置的類會拋出一些異常之外, 程序猿也可以手動拋出某個異常. 使用 throw 關鍵字完成這個操作

public static void main(String[] args) { 
 System.out.println(divide(10, 0)); 
} 
public static int divide(int x, int y) { 
 if (y == 0) { 
 throw new ArithmeticException("拋出除 0 異常"); 
 } 
 return x / y; 
} 
// 執(zhí)行結果
Exception in thread "main" java.lang.ArithmeticException: 拋出除 0 異常
 at demo02.Test.divide(Test.java:14) 
 at demo02.Test.main(Test.java:9)

在這個代碼中, 我們可以根據(jù)實際情況來拋出需要的異常. 在構造異常對象同時可以指定一些描述性信息.

異常說明
我們在處理異常的時候, 通常希望知道這段代碼中究竟會出現(xiàn)哪些可能的異常.

我們可以使用 throws 關鍵字, 把可能拋出的異常顯式的標注在方法定義的位置. 從而提醒調(diào)用者要注意捕獲這些異常.

public static int divide(int x, int y) throws ArithmeticException { 
 if (y == 0) { 
 throw new ArithmeticException("拋出除 0 異常"); 
 } 
 return x / y; 
}

三、 自定義異常類

Java 中雖然已經(jīng)內(nèi)置了豐富的異常類, 但是我們實際場景中可能還有一些情況需要我們對異常類進行擴展, 創(chuàng)建符合我們實際情況的異常.

我們先看一下其他的異常大概是個怎么樣的一個體系:

在這里插入圖片描述

空指針異常是繼承了個運行時異常,不過他里面的方法寫的不是很多,也就是兩個幫父類的構造方法,所以按照它這樣的我們也可以寫一個自己的異常。

創(chuàng)建一個異常類:

在這里插入圖片描述

使用:

在這里插入圖片描述

結果:

在這里插入圖片描述

以上就是我們的一個自定義異常

那么我們可不可以繼承Exception呢?

在這里插入圖片描述

這里發(fā)現(xiàn)報錯了,為什么?我們在來看一下異常體系結構

在這里插入圖片描述

這個時候編譯器不知道是編譯時異常還是運行時異常,所以默認選擇權限小的編譯時異常,這個時候我們要拋出異常

在這里插入圖片描述

上面的沒有報錯了下面的開始了?為什么?因為我們拋出編譯時異常,我們要try catch一下:

在這里插入圖片描述

所以這個就是一個自定義異常。

在舉一個例子:

例如, 我們實現(xiàn)一個用戶登陸功能:(如果用戶名錯誤處理用戶名的錯誤,密碼錯誤處理密碼錯誤)

在這里插入圖片描述

此時我們在處理用戶名密碼錯誤的時候可能就需要拋出兩種異常. 我們可以基于已有的異常類進行擴展(繼承), 創(chuàng)建和我們業(yè)務相關的異常類

在這里插入圖片描述

自己寫的類

我們可以在login里面這樣寫:

在這里插入圖片描述

主方法:

在這里插入圖片描述

這樣就是使用我們自己的異常。

注意事項:

  • 自定義異常通常會繼承自 Exception 或者 RuntimeException
  • 繼承自 Exception 的異常默認是受查異常
  • 繼承自 RuntimeException 的異常默認是非受查異常.

以上就是異常的全部內(nèi)容了,如果有什么不對的地方歡迎評論指正謝謝!!

到此這篇關于Java 知識難點之異常的認知與使用詳解的文章就介紹到這了,更多相關Java 異常內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java實現(xiàn)洗牌發(fā)牌的方法

    Java實現(xiàn)洗牌發(fā)牌的方法

    這篇文章主要介紹了Java實現(xiàn)洗牌發(fā)牌的方法,涉及java針對數(shù)組的遍歷與排序操作相關技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-07-07
  • Java中字符串轉int數(shù)據(jù)類型的三種方式

    Java中字符串轉int數(shù)據(jù)類型的三種方式

    這篇文章主要介紹了Java中字符串轉int數(shù)據(jù)類型的三種方式,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-03-03
  • 在SpringBoot項目中解決依賴沖突問題的方法

    在SpringBoot項目中解決依賴沖突問題的方法

    在SpringBoot項目中,依賴沖突是一個常見的問題,特別是當項目引入多個第三方庫或框架時,依賴沖突可能導致編譯錯誤、運行時異?;虿豢深A測的行為,本文給大家介紹了如何在SpringBoot項目中解決以來沖突問題的方法,需要的朋友可以參考下
    2024-01-01
  • java并發(fā)編程synchronized底層實現(xiàn)原理

    java并發(fā)編程synchronized底層實現(xiàn)原理

    這篇文章主要介紹了java并發(fā)編程synchronized底層實現(xiàn)原理
    2022-02-02
  • Java并發(fā)編程之線程池實現(xiàn)原理詳解

    Java并發(fā)編程之線程池實現(xiàn)原理詳解

    池化思想是一種空間換時間的思想,期望使用預先創(chuàng)建好的對象來減少頻繁創(chuàng)建對象的性能開銷,java中有多種池化思想的應用,例如:數(shù)據(jù)庫連接池、線程池等,下面就來具體講講
    2023-05-05
  • 解析Java中的默認方法

    解析Java中的默認方法

    這篇文章主要介紹了Java中的默認方法,包括繼承和調(diào)用等Java入門學習中的基礎知識,需要的朋友可以參考下
    2015-07-07
  • Spring使用redis遇到的問題及解決方案

    Spring使用redis遇到的問題及解決方案

    這篇文章主要介紹了Spring使用redis遇到的問題及解決方案,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-04-04
  • Spring中BeanFactory?FactoryBean和ObjectFactory的三種的區(qū)別

    Spring中BeanFactory?FactoryBean和ObjectFactory的三種的區(qū)別

    關于FactoryBean?和?BeanFactory的對比文章比較多,但是對ObjectFactory的描述就比較少,今天我們對比下這三種的區(qū)別,感興趣的朋友跟隨小編一起看看吧
    2023-01-01
  • 基于Java Callable接口實現(xiàn)線程代碼實例

    基于Java Callable接口實現(xiàn)線程代碼實例

    這篇文章主要介紹了基于Java Callable接口實現(xiàn)線程代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-08-08
  • Spring Cloud引入Eureka組件,完善服務治理

    Spring Cloud引入Eureka組件,完善服務治理

    這篇文章主要介紹了Spring Cloud引入Eureka組件,完善服務治理的過程詳解,幫助大家更好的理解和使用spring cloud,感興趣的朋友可以了解下
    2021-02-02

最新評論