中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

網(wǎng)站制作_做網(wǎng)站_耐思智慧找客源免費(fèi)用哪個(gè)軟件好

網(wǎng)站制作_做網(wǎng)站_耐思智慧,找客源免費(fèi)用哪個(gè)軟件好,wordpress騰訊云cos插件,建立能網(wǎng)上交易的網(wǎng)站多少錢在程序運(yùn)行時(shí),如果遇到問題(比如除以零、文件找不到等),程序會(huì)發(fā)生異常。異常就像是程序的“錯(cuò)誤提醒”,當(dāng)程序運(yùn)行中出錯(cuò)時(shí),它會(huì)停止,給出一個(gè)錯(cuò)誤信息。我們可以通過異常處理來控制這些錯(cuò)誤&a…

在程序運(yùn)行時(shí),如果遇到問題(比如除以零、文件找不到等),程序會(huì)發(fā)生異常。異常就像是程序的“錯(cuò)誤提醒”,當(dāng)程序運(yùn)行中出錯(cuò)時(shí),它會(huì)停止,給出一個(gè)錯(cuò)誤信息。我們可以通過異常處理來控制這些錯(cuò)誤,避免程序崩潰。異常處理機(jī)制基于“try-catch-finally”語法。

1.異常的分類

  • 編譯時(shí)異常(Checked Exception):這種異常是編譯器檢查到的,程序必須處理這種異常。比如,文件找不到時(shí),Java會(huì)要求你去處理這個(gè)問題。必須捕獲或聲明處理。

    • 例子:IOException(文件操作時(shí)出現(xiàn)錯(cuò)誤)。
  • 運(yùn)行時(shí)異常(Unchecked Exception):這種異常發(fā)生在程序運(yùn)行時(shí),通常是一些小錯(cuò)誤,程序員可以選擇是否處理它。比如,除以零就是一個(gè)運(yùn)行時(shí)異常。RuntimeException是 Java 中常見的運(yùn)行時(shí)異常,它是所有 運(yùn)行時(shí)異常(Unchecked Exceptions)類的父類。RuntimeException 及其子類的異常通常是在程序運(yùn)行時(shí)拋出的,而不像 Checked Exception(如 IOException、SQLException 等)那樣需要顯式地在方法簽名中聲明或捕獲。不需要顯式捕獲,但可以捕獲。下面第五點(diǎn)有關(guān)于RuntimeException的詳細(xì)介紹。

    • 例子:ArithmeticException(除以零),NullPointerException(空指針錯(cuò)誤)。

2.異常處理

Java提供了try-catch-finally語法來處理異常。

2.1 try-catch:捕獲異常并處理

  • try塊中包含可能會(huì)拋出異常的代碼。
  • catch塊用于捕獲特定類型的異常。
    try {int result = 10 / 0; // 可能會(huì)拋出 ArithmeticException
    } catch (ArithmeticException e) {System.out.println("除以零錯(cuò)誤:" + e.getMessage());
    }
    

2.2 finally

無論是否發(fā)生異常,finally中的代碼總是會(huì)執(zhí)行。通常用于清理資源,比如關(guān)閉文件流、數(shù)據(jù)庫連接等。

try {// 可能發(fā)生異常的代碼
} catch (Exception e) {// 異常處理代碼
} finally {// 清理資源的代碼
}

示例:

import java.io.FileReader;
import java.io.IOException;public class FinallyExample {public static void main(String[] args) {FileReader file = null;try {// 嘗試打開文件并讀取file = new FileReader("test.txt");  // 假設(shè)文件存在int data = file.read();System.out.println((char) data);} catch (IOException e) {System.out.println("文件讀取失敗:" + e.getMessage());} finally {// 確保文件流總是關(guān)閉,即使發(fā)生了異常try {if (file != null) {file.close();System.out.println("文件已關(guān)閉。");}} catch (IOException e) {System.out.println("關(guān)閉文件時(shí)出錯(cuò):" + e.getMessage());}}}
}
/*
輸出:
文件已關(guān)閉。
*/

?解釋:

  • try 塊中我們嘗試打開一個(gè)文件并讀取其中的內(nèi)容。
  • 如果文件讀取過程中沒有出現(xiàn)異常,finally 塊會(huì)確保文件流被關(guān)閉。
  • finally 塊中的代碼無論是否發(fā)生異常都會(huì)執(zhí)行,這對(duì)于資源管理(如關(guān)閉文件流、數(shù)據(jù)庫連接等)非常重要。

3.拋出異常

可以通過throw關(guān)鍵字手動(dòng)拋出一個(gè)異常。通過throws聲明方法可能拋出的異常。

3.1 throw:用來拋出一個(gè)異常對(duì)象。

throw new ArithmeticException("除以零異常");

3.2 throws:用來聲明方法可能拋出的異常。

public void myMethod() throws IOException {// 可能拋出IOException的方法
}

綜合使用示例:?

public class ThrowFinallyExample {public static void main(String[] args) {try {processFile("test.txt");} catch (IOException e) {System.out.println("捕獲到異常: " + e.getMessage());}}// 處理文件的方法,可能會(huì)拋出 IOExceptionpublic static void processFile(String fileName) throws IOException {try {System.out.println("開始處理文件:" + fileName);// 假設(shè)處理過程中發(fā)生了異常if (fileName == null) {throw new IOException("文件名不能為空!");}System.out.println("文件處理完成。");} catch (IOException e) {System.out.println("處理文件時(shí)發(fā)生異常:" + e.getMessage());throw e;  // 將異常拋到外層} finally {// 這里模擬資源關(guān)閉,如果發(fā)生了錯(cuò)誤,就拋出異常System.out.println("資源清理中...");if (fileName == null) {throw new IOException("資源清理失敗:文件名為空!");}System.out.println("資源清理完成。");}}
}
/*
輸出:
開始處理文件:test.txt
資源清理中...
資源清理完成。
*/

解釋:

  • processFile 方法中,首先模擬文件處理過程中發(fā)生的 IOException。
  • catch 捕獲并處理該異常后,將其重新拋出,傳遞到方法外層。
  • finally 塊中,無論是否發(fā)生異常,都執(zhí)行資源清理的代碼。如果清理過程中發(fā)生了問題,我們會(huì)拋出一個(gè)新的異常。

3.3 總結(jié):

  1. throw:用于顯式拋出異常。你可以在代碼中主動(dòng)拋出異常,以便在某些條件不滿足時(shí)提前中止執(zhí)行,提示錯(cuò)誤。
  2. finally:用于保證無論是否發(fā)生異常,某些代碼都會(huì)執(zhí)行,通常用于清理工作,如關(guān)閉文件流、數(shù)據(jù)庫連接等資源。
  • throw 拋出的異常需要在 try-catch 中進(jìn)行捕獲,或者通過 throws 聲明拋出。
  • finally 塊中的代碼始終會(huì)執(zhí)行,即使 try 塊或 catch 塊拋出異常。

4.常見的異常類

4.1 Throwable:是Java異常體系的根類,所有異常類的父類。

4.1.1?Error

Error 主要指系統(tǒng)級(jí)錯(cuò)誤,通常不應(yīng)該嘗試捕獲這些錯(cuò)誤。因?yàn)橐坏┏霈F(xiàn)了 Error 類型的異常,程序通常會(huì)無法恢復(fù),例如 OutOfMemoryError?或StackOverflowError。在實(shí)際開發(fā)中,遇到這類錯(cuò)誤時(shí)通常是代碼本身或者運(yùn)行環(huán)境出現(xiàn)了問題,需要從根本上修復(fù),而不是捕獲異常后繼續(xù)執(zhí)行(即一般不需要捕獲,而需要你手動(dòng)把代碼改正確來)。

4.1.2 Exception

Exception 是程序中的常見錯(cuò)誤,我們可以通過 try-catch 語句進(jìn)行捕獲和處理。常見的異常包括 IOExceptionArithmeticException、NullPointerException 等。我們需要根據(jù)具體異常選擇合適的處理方式。

4.2 常見的異常類

4.2.1 IOException

輸入輸出操作異常,例如文件讀取時(shí)文件不存在或者無法讀取就會(huì)拋出IOException錯(cuò)誤。

import java.io.*;public class IOExceptionExample {public static void main(String[] args) {try {// 打開一個(gè)不存在的文件,會(huì)拋出 IOExceptionFileReader file = new FileReader("nonexistentfile.txt");BufferedReader reader = new BufferedReader(file);reader.read();reader.close();} catch (IOException e) {// 捕獲并處理 IOExceptionSystem.out.println("文件操作異常:" + e.getMessage());}}
}

解釋:代碼嘗試打開一個(gè)不存在的文件,導(dǎo)致拋出 IOException。在 catch 塊中,我們捕獲該異常并打印錯(cuò)誤信息,而不是讓程序崩潰。


4.2.2 NullPointerException

當(dāng)你試圖訪問或操作一個(gè) null 對(duì)象時(shí),JVM 無法執(zhí)行相關(guān)操作,因此拋出 NullPointerException。這種異常通常會(huì)發(fā)生在以下幾種情況中:

  • 試圖調(diào)用 null 引用的實(shí)例方法。
  • 試圖訪問 null 引用的字段。
  • 試圖獲取 null 引用的數(shù)組長(zhǎng)度。
  • 試圖將 null 引用傳遞給需要非 null 參數(shù)的方法。
public class NullPointerExceptionExample {public static void main(String[] args) {try {String str = null;System.out.println(str.length());  // str 為 null,會(huì)拋出 NullPointerException} catch (NullPointerException e) {// 捕獲并處理空指針異常System.out.println("發(fā)生了空指針異常: " + e.getMessage());}}
}

解釋:strnull,調(diào)用 str.length() 會(huì)拋出 NullPointerException。我們通過 try-catch 捕獲該異常,避免程序崩潰。


4.2.3 ArithmeticException

算術(shù)運(yùn)算異常,例如當(dāng)你進(jìn)行除法操作時(shí),如果除數(shù)為零,程序會(huì)拋出 ArithmeticException。

public class ArithmeticExceptionExample {public static void main(String[] args) {try {int result = 10 / 0;  // 除以零,拋出 ArithmeticException} catch (ArithmeticException e) {// 捕獲并處理除零錯(cuò)誤System.out.println("發(fā)生了算術(shù)異常: " + e.getMessage());}}
}

解釋:除以零會(huì)拋出 ArithmeticException,我們捕獲異常并輸出錯(cuò)誤信息,而不是讓程序崩潰。


4.2.4 ArrayIndexOutOfBoundsException

當(dāng)你嘗試訪問一個(gè)數(shù)組時(shí),使用了無效的索引(即越界索引)時(shí),會(huì)拋出ArrayIndexOutOfBoundsException異常。

public class ArrayIndexOutOfBoundsExceptionExample {public static void main(String[] args) {int[] arr = new int[3];  // 創(chuàng)建一個(gè)長(zhǎng)度為 3 的數(shù)組try {// 嘗試訪問不存在的索引,數(shù)組長(zhǎng)度為 3,最大索引為 2arr[5] = 10;  // 這會(huì)拋出 ArrayIndexOutOfBoundsException} catch (ArrayIndexOutOfBoundsException e) {System.out.println("發(fā)生了數(shù)組下標(biāo)越界異常: " + e.getMessage());}}
}

解釋:數(shù)組 arr 的長(zhǎng)度為 3,它的有效索引是 0, 1, 2。但是我們嘗試訪問索引 5,這是越界的,導(dǎo)致 ArrayIndexOutOfBoundsException 異常。通過 try-catch 語句捕獲異常,我們避免了程序崩潰,并輸出了錯(cuò)誤信息。


4.2.5 ClassNotFoundException

ClassNotFoundExceptionException 類的子類,通常發(fā)生在 動(dòng)態(tài)加載類 時(shí),如果找不到指定的類,會(huì)拋出此異常。常見于使用反射、Class.forName() 或類加載器時(shí)。

發(fā)生的原因:
  • 你試圖通過 Class.forName()、ClassLoader.loadClass() 等方法動(dòng)態(tài)加載一個(gè)類,但該類在 classpath 中無法找到。
  • 這通常發(fā)生在類路徑配置錯(cuò)誤,或者嘗試加載一個(gè)未編譯或缺失的類時(shí)。
    public class ClassNotFoundExceptionExample {public static void main(String[] args) {try {// 使用 Class.forName 加載不存在的類Class.forName("com.example.NonExistentClass");} catch (ClassNotFoundException e) {System.out.println("發(fā)生了類未找到異常: " + e.getMessage());}}
    }
    

    解釋:這里我們使用 Class.forName("com.example.NonExistentClass") 來加載一個(gè)不存在的類,這會(huì)拋出 ClassNotFoundException 異常。通過 try-catch 捕獲異常并輸出錯(cuò)誤信息,避免了程序崩潰。

解決方法:

  • 確保類路徑配置正確,類文件已經(jīng)編譯并位于 classpath 下。
  • 在動(dòng)態(tài)加載類之前,可以使用 ClassLoadergetResource()getResourceAsStream() 等方法檢查類是否存在。
    ClassLoader classLoader = getClass().getClassLoader();
    if (classLoader.getResource("com/example/NonExistentClass.class") != null) {// 類存在,可以加載Class.forName("com.example.NonExistentClass");
    } else {System.out.println("類文件不存在!");
    }
    
    反射中使用 Class.forName()

    通常情況下,我們會(huì)用反射動(dòng)態(tài)加載類,尤其是在類名只有在運(yùn)行時(shí)才能確定時(shí)。

    public class ReflectionExample {public static void main(String[] args) {try {// 動(dòng)態(tài)加載一個(gè)類Class<?> clazz = Class.forName("java.util.ArrayList");System.out.println("加載成功: " + clazz.getName());} catch (ClassNotFoundException e) {System.out.println("類未找到: " + e.getMessage());}}
    }
    

    解釋:

  • 這段代碼成功加載了 java.util.ArrayList 類并打印出類的名稱。
  • 如果 Class.forName() 中提供的類名無法找到,程序會(huì)拋出 ClassNotFoundException。

4.2.6 FileNotFoundException(文件未找到異常):

  • FileNotFoundException 是一種輸入輸出異常,通常發(fā)生在你嘗試訪問一個(gè)不存在的文件時(shí)。
  • 比如,嘗試打開一個(gè)根本沒有的文件,就會(huì)拋出這個(gè)異常。
    File file = new File("nonexistentfile.txt");
    FileReader fr = new FileReader(file);  // 如果文件不存在,會(huì)拋出 FileNotFoundException
    

    如何避免?

  • 在訪問文件時(shí),先檢查文件是否存在:

    File file = new File("nonexistentfile.txt");
    if (file.exists()) {FileReader fr = new FileReader(file);
    } else {System.out.println("文件不存在!");
    }
    

    4.2.7 SQLException(SQL 異常):

  • SQLException 是數(shù)據(jù)庫操作中常見的異常,通常發(fā)生在數(shù)據(jù)庫查詢失敗時(shí)。
  • 比如,執(zhí)行錯(cuò)誤的 SQL 查詢語句時(shí),會(huì)拋出這個(gè)異常。
    Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/test", "user", "password");
    Statement stmt = conn.createStatement();
    stmt.executeUpdate("INVALID SQL QUERY");  // 會(huì)拋出 SQLException
    

    如何避免?

  • 在執(zhí)行 SQL 操作時(shí),確保 SQL 語句的正確性,并正確處理異常。
    try {stmt.executeUpdate("SELECT * FROM users");  // 正確的 SQL 查詢
    } catch (SQLException e) {System.out.println("SQL 執(zhí)行錯(cuò)誤:" + e.getMessage());
    }
    

5.自定義異常

5.1 解釋:

可以根據(jù)需要定義自己的異常類,通常自定義異常類需要繼承ExceptionRuntimeException。

class MyException extends Exception {public MyException(String message) {super(message);}
}public class Test {public static void test() throws MyException {throw new MyException("自定義異常");}public static void main(String[] args) {try {test();} catch (MyException e) {System.out.println("捕獲到自定義異常:" + e.getMessage());}}
}

5.2 關(guān)于RuntimeException:

5.2.1?RuntimeException 的基本介紹

  • 繼承關(guān)系RuntimeException 繼承自 Exception 類,并且是 未檢查異常(Unchecked Exception)的基類。
  • 運(yùn)行時(shí)異常:運(yùn)行時(shí)異常通常表示程序的邏輯錯(cuò)誤或不合適的狀態(tài),開發(fā)者不需要強(qiáng)制捕獲這些異常。
  • 不需要顯式聲明:與受檢查異常不同,RuntimeException 不要求你在方法中使用 throws 聲明它,且也不強(qiáng)制在代碼中進(jìn)行 try-catch 捕獲。

5.2.2 常見的 RuntimeException 子類

  • NullPointerException:訪問空對(duì)象引用時(shí)拋出的異常。
  • ArithmeticException:發(fā)生算術(shù)運(yùn)算錯(cuò)誤時(shí)拋出的異常,例如除以零。
  • ArrayIndexOutOfBoundsException:訪問數(shù)組時(shí),索引越界時(shí)拋出的異常。
  • ClassCastException:進(jìn)行不合法的類型轉(zhuǎn)換時(shí)拋出的異常。
  • IllegalArgumentException:當(dāng)方法接收到不合法的參數(shù)時(shí)拋出的異常。
  • IllegalStateException:方法被調(diào)用時(shí),當(dāng)前對(duì)象狀態(tài)不合法時(shí)拋出的異常。

5.2.3?RuntimeException 的特點(diǎn)

  • 不需要捕獲RuntimeException 是未檢查異常,所以開發(fā)者不必在代碼中顯式捕獲它,也不必在方法簽名中聲明它。
  • 通常是程序錯(cuò)誤:運(yùn)行時(shí)異常通常是因?yàn)榇a中的邏輯錯(cuò)誤或者數(shù)據(jù)錯(cuò)誤,比如訪問空指針、數(shù)組越界等。修復(fù)這些異常一般需要修改代碼邏輯。

5.2.4 如何使用 RuntimeException

雖然大多數(shù)情況下,RuntimeException 及其子類是由 JVM 自動(dòng)拋出的,但你也可以在自己的代碼中顯式拋出 RuntimeException 或其子類,來指示某種錯(cuò)誤。

拋出 RuntimeException 示例:

public class RuntimeExceptionExample {public static void main(String[] args) {try {checkAge(15);  // 傳入一個(gè)非法的年齡值,拋出異常} catch (RuntimeException e) {System.out.println("捕獲到異常: " + e.getMessage());}}// 自定義方法,檢查年齡是否合法public static void checkAge(int age) {if (age < 18) {throw new IllegalArgumentException("年齡不能小于 18!");}System.out.println("年齡合格:" + age);}
}
/*
捕獲到異常: 年齡不能小于 18!
*/

解釋:

  • checkAge 方法中,如果傳入的年齡小于 18,則主動(dòng)拋出一個(gè) IllegalArgumentException 異常,表示年齡不合法。
  • RuntimeException 的子類 IllegalArgumentException 被拋出,并在 catch 塊中捕獲和處理。

5.2.5 為什么使用 RuntimeException

RuntimeException 和其他未檢查異常(Unchecked Exception)通常用于:

  • 表示代碼邏輯中的錯(cuò)誤,而不是外部條件導(dǎo)致的異常。
  • 表示不容易預(yù)見或者不容易恢復(fù)的錯(cuò)誤,開發(fā)者可以通過修改代碼來避免這種錯(cuò)誤發(fā)生。
  • 用于捕捉錯(cuò)誤輸入、錯(cuò)誤參數(shù)、程序不符合邏輯的狀態(tài)等情況。

5.2.6?RuntimeException 與其他異常的區(qū)別

特性RuntimeExceptionIOException、SQLException
檢查異常/非檢查異常非檢查異常(Unchecked Exception)檢查異常(Checked Exception)
是否強(qiáng)制捕獲不強(qiáng)制捕獲或聲明強(qiáng)制捕獲或聲明
拋出原因程序邏輯錯(cuò)誤、非法操作外部因素、資源不可用等
常見場(chǎng)景空指針、除零、數(shù)組越界等文件讀寫失敗、數(shù)據(jù)庫操作失敗等

5.2.7 何時(shí)使用 RuntimeException

你可以在以下情況使用 RuntimeException

  • 不合法的參數(shù):當(dāng)方法的參數(shù)不符合預(yù)期時(shí)(如負(fù)數(shù)、空值等),你可以拋出一個(gè) IllegalArgumentException。
  • 非法的狀態(tài):當(dāng)對(duì)象的狀態(tài)不適合調(diào)用某個(gè)方法時(shí),可以拋出一個(gè) IllegalStateException。
  • 算術(shù)錯(cuò)誤:如除以零時(shí),拋出 ArithmeticException
  • 不合理的類型轉(zhuǎn)換:如進(jìn)行不合法的類型強(qiáng)制轉(zhuǎn)換,拋出 ClassCastException。

6.異常鏈

異常鏈(Exception Chaining)是指在捕獲異常時(shí),將原始異常作為另一個(gè)異常的原因(cause)拋出。Java 提供了一種機(jī)制,允許我們?cè)趻伋鲂碌漠惓r(shí),把原本拋出的異常附加到新的異常中。這樣做可以幫助我們保留原始異常的詳細(xì)信息,方便后續(xù)調(diào)試和問題定位。

6.1?異常鏈的作用

異常鏈的主要作用是幫助我們追蹤問題的根源。當(dāng)我們捕獲到異常后,可以將其作為另一個(gè)異常的原因拋出,這樣就能保留原始異常的信息,便于定位問題的源頭。例如,捕獲一個(gè) SQLException,并將其作為 IOException 的原因重新拋出,方便上層調(diào)用者了解到底是哪里出的問題。

6.2 異常鏈的基本使用

Java 提供了 Throwable 類的構(gòu)造方法,允許我們?cè)趻伋霎惓r(shí)指定一個(gè)原始的異常對(duì)象:

public Throwable(String message, Throwable cause)

public Throwable(String message, Throwable cause) 是 Java 中 Throwable 類的一個(gè)構(gòu)造方法,它用于創(chuàng)建一個(gè)帶有 錯(cuò)誤消息原始異常 的異常對(duì)象。我們通常使用它來創(chuàng)建新的異常,同時(shí)保存引起該異常的原始原因。

6.2.1?構(gòu)造方法的參數(shù)說明

  • String message:這個(gè)參數(shù)是一個(gè) 錯(cuò)誤消息,用于描述當(dāng)前異常的具體情況。通常是一個(gè)簡(jiǎn)短的字符串,用來說明異常的原因或上下文。例如:"File not found"。
  • Throwable cause:這個(gè)參數(shù)是另一個(gè)異常對(duì)象,表示 導(dǎo)致當(dāng)前異常的原始異常。它通常是一個(gè)已經(jīng)存在的異常對(duì)象,我們把它傳遞到新的異常中來形成 異常鏈

6.2.2?構(gòu)造函數(shù)的作用

  • 當(dāng)我們?cè)诔绦蛑胁东@到一個(gè)異常,并且想要拋出一個(gè)新的異常時(shí),可以通過這個(gè)構(gòu)造函數(shù)將 原始異常cause)傳遞給新異常。
  • 這樣做的目的是保留 原始異常 的信息,幫助開發(fā)者追蹤錯(cuò)誤的根源。它是一種 異常鏈 技術(shù),可以讓我們知道一個(gè)異常是如何引發(fā)其他異常的。

6.2.3?為什么使用這個(gè)構(gòu)造函數(shù)?

使用這個(gè)構(gòu)造函數(shù)的好處是:

  • 我們可以 拋出新的異常,并且 保留原始異常的上下文信息,從而有助于追蹤問題的根源。
  • 通過 getCause() 方法,后續(xù)的異常處理者能夠獲取到原始異常并進(jìn)行處理。

6.2.4?例子:如何使用 Throwable(String message, Throwable cause)

假設(shè)我們?cè)谔幚硪粋€(gè)文件操作時(shí)發(fā)生了異常,我們可以通過異常鏈來傳遞原始的 IOException 異常,使得上層調(diào)用者能夠獲取到詳細(xì)的錯(cuò)誤信息。

代碼示例:
public class ExceptionChainingDemo {public static void main(String[] args) {try {processFile();} catch (Exception e) {e.printStackTrace();}}public static void processFile() throws Exception {try {openFile();} catch (Exception e) {// 將原始異常 e 包裝到一個(gè)新的異常中并拋出throw new Exception("Failed to process the file", e);}}public static void openFile() throws Exception {// 模擬拋出文件操作異常throw new java.io.IOException("File not found");}
}
輸出:
java.lang.Exception: Failed to process the fileat ExceptionChainingDemo.processFile(ExceptionChainingDemo.java:9)at ExceptionChainingDemo.main(ExceptionChainingDemo.java:4)
Caused by: java.io.IOException: File not foundat ExceptionChainingDemo.openFile(ExceptionChainingDemo.java:15)at ExceptionChainingDemo.processFile(ExceptionChainingDemo.java:7)... 1 more

6.2.5?解釋

  • 在上面的代碼中:
    • openFile() 方法拋出了一個(gè) IOException 異常(模擬文件未找到的情況)。
    • processFile() 方法中,我們捕獲了這個(gè) IOException 異常,并且通過 new Exception("Failed to process the file", e) 創(chuàng)建了一個(gè)新的 Exception 異常。
    • 這里的 "Failed to process the file" 是新的異常的描述信息,而 e(即原始的 IOException 異常)被傳遞作為 原始異常(即 cause)。
  • 當(dāng)我們打印異常信息時(shí),printStackTrace() 顯示了當(dāng)前異常的信息,并且通過 Caused by 顯示了引發(fā)當(dāng)前異常的原始異常。

?

6.2.6 使用 ExceptionRuntimeException 創(chuàng)建異常鏈

Exception 類和 RuntimeException 類都提供了帶有 cause 參數(shù)的構(gòu)造函數(shù),因此你可以在拋出這兩種異常時(shí)都使用異常鏈。

示例:創(chuàng)建 RuntimeException 異常鏈
public class RuntimeExceptionChaining {public static void main(String[] args) {try {method1();} catch (RuntimeException e) {// 捕獲并輸出異常信息,顯示異常鏈System.out.println("Caught exception: " + e);Throwable cause = e.getCause();if (cause != null) {System.out.println("Cause: " + cause);}}}public static void method1() {try {method2();} catch (RuntimeException e) {// 捕獲 method2 中的異常,并將其作為 method1 的原因throw new RuntimeException("Error occurred in method1", e);}}public static void method2() {// 模擬拋出一個(gè) RuntimeExceptionthrow new RuntimeException("An error occurred in method2");}
}

輸出:

Caught exception: java.lang.RuntimeException: Error occurred in method1
Cause: java.lang.RuntimeException: An error occurred in method2

6.2.7 為什么要使用異常鏈?

  1. 保留原始異常信息:當(dāng)我們?cè)诓东@到一個(gè)異常后,可以將它附加到一個(gè)新的異常中,這樣上層代碼就可以通過 getCause() 方法查看到原始的異常信息,幫助定位問題。

  2. 幫助追蹤錯(cuò)誤的根源:異常鏈可以讓我們清楚地看到異常是如何傳播的,特別是在復(fù)雜的系統(tǒng)中,錯(cuò)誤可能從底層層級(jí)一直傳遞到上層應(yīng)用,使用異常鏈可以更容易追蹤整個(gè)錯(cuò)誤過程。

  3. 提高代碼可讀性:通過異常鏈,能夠避免在捕獲異常后丟失原始的錯(cuò)誤信息,增強(qiáng)代碼的可讀性和可維護(hù)性。

6.2.8?getCause()printStackTrace()

  • getCause():可以用來獲取原始異常(如果存在的話)。
  • printStackTrace():會(huì)打印當(dāng)前異常以及異常鏈中的所有異常。
6.2.8.1?getCause() 方法

getCause() 方法用于獲取當(dāng)前異常的原始異常(即引發(fā)當(dāng)前異常的異常)。它是 Throwable 類的一部分,所有異常類(包括 ExceptionError)都繼承自 Throwable,因此都可以使用該方法。

1. 功能
  • getCause() 返回的是一個(gè) Throwable 對(duì)象,它代表的是導(dǎo)致當(dāng)前異常發(fā)生的原始異常(如果存在的話)。
  • 如果當(dāng)前異常是直接拋出的,沒有原始異常,則返回 null。
2. 示例:
public class GetCauseExample {public static void main(String[] args) {try {method1();} catch (Exception e) {// 獲取并打印原始異常System.out.println("Caught exception: " + e.getMessage());if (e.getCause() != null) {System.out.println("Cause: " + e.getCause());}}}public static void method1() throws Exception {try {method2();} catch (Exception e) {// 捕獲異常并將其作為原因拋出throw new Exception("Error in method1", e);}}public static void method2() throws Exception {// 模擬拋出一個(gè)異常throw new Exception("Error in method2");}
}

輸出:

Caught exception: Error in method1
Cause: java.lang.Exception: Error in method2
3.?解釋
  • method2() 拋出了一個(gè)異常:"Error in method2"。
  • method1() 捕獲了該異常,并將它作為原因(cause)拋出了一個(gè)新的異常:"Error in method1"。
  • main() 方法中,我們捕獲了這個(gè)新的異常,并通過 getCause() 方法獲取到原始的異常信息。
6.2.8.2?printStackTrace() 方法

printStackTrace()Throwable 類的一個(gè)方法,它用于打印異常的堆棧跟蹤信息。堆棧跟蹤信息通常包含以下內(nèi)容:

  • 異常的類型和消息。
  • 異常發(fā)生時(shí)的方法調(diào)用棧(即方法的調(diào)用路徑)。
  • 異常發(fā)生的具體位置(行號(hào)和類名)。
1. 功能
  • printStackTrace() 方法會(huì)將異常的堆棧信息輸出到控制臺(tái),幫助開發(fā)人員了解異常發(fā)生的詳細(xì)上下文。
2. 示例:
public class PrintStackTraceExample {public static void main(String[] args) {try {method1();} catch (Exception e) {// 打印異常的堆棧信息e.printStackTrace();}}public static void method1() throws Exception {try {method2();} catch (Exception e) {// 捕獲異常并將其作為原因拋出throw new Exception("Error in method1", e);}}public static void method2() throws Exception {// 模擬拋出一個(gè)異常throw new Exception("Error in method2");}
}

輸出:

java.lang.Exception: Error in method1at PrintStackTraceExample.method1(PrintStackTraceExample.java:10)at PrintStackTraceExample.main(PrintStackTraceExample.java:5)
Caused by: java.lang.Exception: Error in method2at PrintStackTraceExample.method2(PrintStackTraceExample.java:16)at PrintStackTraceExample.method1(PrintStackTraceExample.java:8)... 1 more
3.?解釋
  • method2() 中,我們拋出了一個(gè)異常 "Error in method2",然后在 method1() 中捕獲該異常并將其作為原因拋出了新的異常 "Error in method1"
  • 當(dāng)在 main() 中捕獲到異常并調(diào)用 printStackTrace() 時(shí),異常信息不僅顯示當(dāng)前異常,還顯示了由原始異常引起的 Caused by 部分。這樣,我們可以清晰地看到異常鏈,追蹤錯(cuò)誤的根本原因。

7.異常的最佳實(shí)踐

  1. 捕獲特定異常:盡量捕獲具體的異常,而不是捕獲Exception
  2. 不要忽略異常:避免捕獲異常后什么都不做,這會(huì)隱藏程序中的問題。
  3. 及時(shí)釋放資源:在finally中關(guān)閉文件流、數(shù)據(jù)庫連接等資源,確保資源能夠正確釋放。
  4. 使用自定義異常:在合適的情況下,定義并拋出自定義異常,提供更加具體的錯(cuò)誤信息。

8.異常的傳遞

在Java中,異??梢栽诜椒▋?nèi)部被捕獲并處理,也可以向上傳遞。異常的傳遞是通過方法聲明中的throws來實(shí)現(xiàn)的。如果方法中拋出了異常且該異常沒有被處理,Java虛擬機(jī)會(huì)將其傳遞給調(diào)用該方法的地方。

8.1 異常傳播

8.1.1 解釋:

如果一個(gè)方法拋出一個(gè)異常,而該方法的調(diào)用者沒有處理(即沒有捕獲或聲明throws),這個(gè)異常將會(huì)被繼續(xù)拋出,直到它被某個(gè)方法捕獲或最終未被捕獲而導(dǎo)致程序終止。

public void methodA() throws Exception {methodB(); // methodB 可能拋出異常
}public void methodB() throws Exception {throw new Exception("Something went wrong");
}

?異常的多層次處理: 在多層方法調(diào)用中,如果外層方法沒有處理異常,內(nèi)層方法拋出的異常就會(huì)一直向上傳遞。

try {methodA(); // methodA 中會(huì)拋出異常
} catch (Exception e) {System.out.println("異常被捕獲:" + e.getMessage());
}

8.1.2 具體代碼舉例:

public class ExceptionHandlingExample {// methodA 拋出 Exceptionpublic void methodA() throws Exception {System.out.println("In methodA");methodB();  // 調(diào)用 methodB,methodB 可能拋出異常}// methodB 拋出一個(gè)異常public void methodB() throws Exception {System.out.println("In methodB");// 模擬拋出異常throw new Exception("Something went wrong in methodB");}public static void main(String[] args) {ExceptionHandlingExample example = new ExceptionHandlingExample();try {example.methodA();  // 調(diào)用 methodA,methodA 中會(huì)調(diào)用 methodB,methodB 拋出異常} catch (Exception e) {// 捕獲異常并處理System.out.println("異常被捕獲: " + e.getMessage());  // 打印異常消息e.printStackTrace();  // 打印異常的堆棧信息}}
}

8.1.3 代碼說明

methodA

  • methodA 聲明 throws Exception,意味著它會(huì)拋出 Exception 類型的異常。
  • methodA 中,我們調(diào)用了 methodB(),而 methodB 可能會(huì)拋出一個(gè)異常。

methodB

methodB 也聲明了 throws Exception,表示該方法可能會(huì)拋出異常。

methodB 中,我們模擬拋出了一個(gè) Exception,并傳遞了錯(cuò)誤消息 "Something went wrong in methodB"

main 方法

  • main 方法中,我們創(chuàng)建了 ExceptionHandlingExample 的實(shí)例,并調(diào)用 methodA()。
  • methodA() 調(diào)用 methodB(),而 methodB() 會(huì)拋出一個(gè)異常,因此 methodA() 也會(huì)拋出異常。
  • try 塊中,我們捕獲了 methodA() 拋出的異常,使用 catch 語句塊處理異常。
  • 我們使用 e.getMessage() 打印異常的消息,并使用 e.printStackTrace() 打印異常的堆棧跟蹤信息。

輸出結(jié)果

In methodA
In methodB
異常被捕獲: Something went wrong in methodB
java.lang.Exception: Something went wrong in methodBat ExceptionHandlingExample.methodB(ExceptionHandlingExample.java:17)at ExceptionHandlingExample.methodA(ExceptionHandlingExample.java:9)at ExceptionHandlingExample.main(ExceptionHandlingExample.java:27)

解釋

  1. 程序首先進(jìn)入 methodA,然后調(diào)用 methodB。
  2. methodB 拋出了一個(gè)異常 "Something went wrong in methodB",并且異常被 methodA 捕獲。
  3. methodA 繼續(xù)拋出該異常,最終在 main 方法中的 try-catch 塊中捕獲到這個(gè)異常。
  4. 異常的消息 "Something went wrong in methodB" 被打印出來,且 e.printStackTrace() 打印了詳細(xì)的堆棧信息,顯示異常是如何從 methodB 傳遞到 methodA 的。

9.捕獲多個(gè)異常

9.1 解釋:

Java 7 引入了多重異常捕獲(Multi-catch),允許在一個(gè) catch 塊中捕獲多個(gè)異常,這樣可以減少重復(fù)的代碼,并提高代碼的可讀性。你只需要在 catch 塊中的異常類型之間使用 |(管道符)進(jìn)行分隔。

9.2 代碼格式

try {// 可能發(fā)生異常的代碼
} catch (IOException | SQLException e) {  // 捕獲多種異常System.out.println("發(fā)生異常:" + e.getMessage());
}

9.3 要求

  • 多個(gè)異常類必須有共同的父類,通常是 Exception 或其子類(例如:IOExceptionSQLException 都是 Exception 的子類)。
  • catch 塊中,捕獲的異常類的對(duì)象(這里是 e)會(huì)變成 Throwable 的父類,因此你不能再對(duì) e 進(jìn)行多態(tài)特有的方法調(diào)用。

9.4 具體例子

假設(shè)我們有兩個(gè)異常:IOException(輸入輸出異常)和 SQLException(SQL 異常)。我們會(huì)模擬一個(gè)程序,在操作文件和數(shù)據(jù)庫時(shí)分別拋出這兩個(gè)異常,并使用 Java 7 的多重異常捕獲來處理。

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.SQLException;public class MultiCatchExample {// 模擬讀取文件public static void readFile() throws IOException {// 模擬文件未找到異常throw new FileNotFoundException("文件未找到");}// 模擬數(shù)據(jù)庫操作public static void connectToDatabase() throws SQLException {// 模擬SQL異常throw new SQLException("數(shù)據(jù)庫連接失敗");}public static void main(String[] args) {try {readFile();  // 可能拋出 IOExceptionconnectToDatabase();  // 可能拋出 SQLException} catch (IOException | SQLException e) {  // 捕獲多種異常System.out.println("發(fā)生異常:" + e.getMessage());}}
}

9.4.1 代碼解釋

  1. readFile() 方法

    • 該方法模擬讀取文件的操作,可能會(huì)拋出 IOException 類型的異常。為了演示,我們使用 FileNotFoundException(它是 IOException 的子類)來模擬文件未找到的異常。
  2. connectToDatabase() 方法

    • 該方法模擬連接數(shù)據(jù)庫的操作,可能會(huì)拋出 SQLException 類型的異常。我們直接拋出一個(gè) SQLException。
  3. main() 方法

    • 我們?cè)?try 塊中依次調(diào)用 readFile()connectToDatabase() 方法,這兩個(gè)方法都有可能拋出異常。
    • catch 塊中,我們使用 | 操作符捕獲了 IOExceptionSQLException,并通過 e.getMessage() 打印了異常消息。

9.4.2 輸出結(jié)果

發(fā)生異常:文件未找到

9.5 總結(jié):

  • 多重異常捕獲:Java 7 引入了多重異常捕獲,允許你在同一個(gè) catch 塊中捕獲多個(gè)異常。你只需使用 | 分隔異常類,如 IOException | SQLException
  • 減少重復(fù)代碼:這種方式讓你避免了為每個(gè)異常寫一個(gè) catch 塊的冗余代碼,從而使代碼更簡(jiǎn)潔、可讀性更強(qiáng)。
  • 共同父類:多個(gè)異常類必須有共同的父類,通常是 Exception 或其子類,否則不能進(jìn)行多重異常捕獲。

10.異常的性能

異常處理會(huì)影響程序的性能,尤其是在頻繁拋出異常的情況下。為了優(yōu)化性能,應(yīng)該避免在正常的程序流程中使用異常。例如,不應(yīng)該使用異常來控制程序流程,尤其是在循環(huán)或頻繁執(zhí)行的代碼塊中。

  1. 異常的成本: 拋出異常是一個(gè)相對(duì)昂貴的操作,因?yàn)樗枰獎(jiǎng)?chuàng)建異常對(duì)象并進(jìn)行堆棧跟蹤。因此,最好在必要時(shí)才拋出異常。

  2. 異常的優(yōu)化

    • 避免過多的try-catch塊,尤其是在循環(huán)中。
    • 捕獲異常的塊應(yīng)盡量簡(jiǎn)短,不要做復(fù)雜的邏輯處理。

11.異常的嵌套與多線程中的異常處理

  1. 嵌套異常: 異??赡軙?huì)嵌套。例如,一個(gè)方法拋出的異常被另一個(gè)方法捕獲并進(jìn)一步拋出,這樣形成了嵌套異常鏈??梢酝ㄟ^getCause()方法獲取引起當(dāng)前異常的根本原因。

    try {throw new IOException("File not found");
    } catch (IOException e) {throw new RuntimeException("Failed to read file", e); // 將 IOException 作為 RuntimeException 的根本原因
    }
    

    使用e.getCause()可以獲取到原始的異常對(duì)象,從而追蹤到真正的錯(cuò)誤源。

  2. 多線程中的異常處理: 在多線程編程中,異常處理稍顯復(fù)雜。每個(gè)線程都有自己的執(zhí)行棧,因此在每個(gè)線程中都可能發(fā)生異常。Java提供了Thread.UncaughtExceptionHandler接口來處理未捕獲的線程異常。

    Thread thread = new Thread(() -> {// 可能拋出異常的代碼
    });
    thread.setUncaughtExceptionHandler((t, e) -> {System.out.println("線程 " + t.getName() + " 拋出了異常:" + e.getMessage());
    });
    thread.start();
    

    通過設(shè)置未捕獲異常處理器,我們可以對(duì)線程中的異常進(jìn)行集中處理,而不會(huì)讓整個(gè)應(yīng)用崩潰。

12.Java 8 引入的異常流處理

在Java 8中,引入了流式API(Stream API),這使得在進(jìn)行流操作時(shí),異常處理變得更加重要。流中的方法(如map()、filter()等)通常要求無異常的輸入,但是你可能會(huì)遇到需要在流中處理異常的場(chǎng)景。

一種常見的方式是通過try-catch包裝流中的異常:

List<String> data = Arrays.asList("1", "2", "abc", "4");List<Integer> result = data.stream().map(str -> {try {return Integer.parseInt(str);} catch (NumberFormatException e) {return null;  // 處理異常,返回null}}).filter(Objects::nonNull).collect(Collectors.toList());System.out.println(result);  // 輸出:[1, 2, 4]

在這種情況下,我們使用了map()來處理每個(gè)元素可能發(fā)生的NumberFormatException異常,并返回null值,最后通過filter()去掉null值。

13.資源管理與自動(dòng)關(guān)閉(Java 7引入的AutoCloseable)

從Java 7開始,引入了自動(dòng)資源管理(ARM),即try-with-resources語句,專門用于處理需要關(guān)閉的資源(如文件、數(shù)據(jù)庫連接等)。資源實(shí)現(xiàn)了AutoCloseable接口,保證無論是否發(fā)生異常,都會(huì)自動(dòng)關(guān)閉資源。

try (FileReader fr = new FileReader("file.txt")) {// 讀取文件
} catch (IOException e) {e.printStackTrace();
} // FileReader 會(huì)在此自動(dòng)關(guān)閉,無論是否發(fā)生異常

這種方式能夠確保即使在異常發(fā)生時(shí),資源也能正確地被釋放,避免了資源泄漏問題。

http://www.risenshineclean.com/news/49823.html

相關(guān)文章:

  • 網(wǎng)站開發(fā)怎么收費(fèi)青島新聞最新今日頭條
  • 設(shè)計(jì)比例網(wǎng)站北京網(wǎng)站優(yōu)化價(jià)格
  • 邢臺(tái)哪里可以做網(wǎng)站怎么引流怎么推廣自己的產(chǎn)品
  • 青州建網(wǎng)站seo高級(jí)優(yōu)化技巧
  • 外貿(mào)企業(yè) 訪問國(guó)外網(wǎng)站網(wǎng)絡(luò)營(yíng)銷的基本方式有哪些
  • 導(dǎo)航網(wǎng)站是怎么做的建站系統(tǒng)源碼
  • 給網(wǎng)站寫文章怎么做無錫網(wǎng)站制作推廣
  • 網(wǎng)站建設(shè)的概念凡科建站靠譜嗎
  • 門戶網(wǎng)站建設(shè)招標(biāo)方nba實(shí)力榜最新排名
  • 百度新疆網(wǎng)站建設(shè)西安網(wǎng)
  • 需要做個(gè)網(wǎng)站長(zhǎng)沙有實(shí)力的關(guān)鍵詞優(yōu)化價(jià)格
  • 南京建行網(wǎng)站外貿(mào)seo網(wǎng)站
  • 深圳市公共資源交易中心官網(wǎng)杭州seo推廣公司
  • 珠海做網(wǎng)站的網(wǎng)絡(luò)公司網(wǎng)址導(dǎo)航瀏覽器下載
  • 杭州營(yíng)銷型網(wǎng)站建設(shè)排名廣告接單平臺(tái)app
  • 哪個(gè)網(wǎng)站做衣服的線上營(yíng)銷策略
  • 重慶建網(wǎng)站推廣價(jià)格創(chuàng)建一個(gè)網(wǎng)站
  • 運(yùn)營(yíng)網(wǎng)站長(zhǎng)沙seo技術(shù)培訓(xùn)
  • 網(wǎng)站建設(shè)優(yōu)惠中ui培訓(xùn)
  • 國(guó)內(nèi)做網(wǎng)站建設(shè)知名的公司怎么優(yōu)化標(biāo)題和關(guān)鍵詞排名
  • 大連做網(wǎng)站billionseo下載愛城市網(wǎng)app官方網(wǎng)站
  • 昆明二級(jí)站seo整站優(yōu)化排名上海最新新聞
  • 汽修網(wǎng)站建設(shè)免費(fèi)推廣營(yíng)銷平臺(tái)
  • 做自媒體發(fā)視頻用哪些網(wǎng)站百度域名查詢官網(wǎng)
  • 一些做系統(tǒng)的網(wǎng)站網(wǎng)絡(luò)服務(wù)器的功能
  • 點(diǎn)開圖片跳到網(wǎng)站怎么做網(wǎng)絡(luò)營(yíng)銷最火的案例
  • 建網(wǎng)站添加付款方式中國(guó)軟文網(wǎng)官網(wǎng)
  • 電商網(wǎng)站產(chǎn)品設(shè)計(jì)優(yōu)化技術(shù)主要是上海專業(yè)seo服務(wù)公司
  • 衢州站電話重慶疫情最新情況
  • 石巖網(wǎng)站建設(shè) 0755seo網(wǎng)絡(luò)排名優(yōu)化