靜網PWA視頻評論

Java的異常處理及應用

2024年01月05日

- txt下載

Java的異常處理及應用
  Java 異常處理是使用Java 語言進行軟體開發和測試腳本開發時不容忽視的問題之一,是否進行異常處理直接關係到開發出的軟體的穩定性和健壯性。本文系統的闡述了 Java 異常處理的原理和方法,並列舉了一些實例,使讀者對 Java 異常處理能有一個全面的認識,理解異常處理機制,能更加靈活和有效地在開發中使用它。下面是小編為大家帶來的關於Java的異常處理及應用的知識,歡迎閱讀。
  Java 異常處理引出
  假設您要編寫一個 Java 程序,該程序讀入用戶輸入的一行文本,並在終端顯示該文本。
  程序如下:
  1 import java.io.*;
  2 public class EchoInput {
  3 public static void main(String args[]){
  4 System.out.println("Enter text to echo:");
  5 InputStreamReader isr = new InputStreamReader(System.in);
  6 BufferedReader inputReader = new BufferedReader(isr);
  7 String inputLine = inputReader.readLine();
  8 System.out.println("Read:" + inputLine);
  9 }
  10 }
  分析上面的代碼,在 EchoInput 類中,第 3 行聲明了 main 方法;第 4 行提示用戶輸入文本;第 5、6 行設置 BufferedReader 對像連接到 InputStreamReader,而 InputStreamReader 又連接到標準輸入流 System.in;第 7 行讀入一行文本;第 8 行用標準輸出流 System.out 顯示出該文本。
  表面看來上面的程序沒有問題,但實際上,EchoInput 類完全可能出現問題。要在調用第 7 行的 readLine 方法時正確讀取輸入,這幾種假設都必須成立:假定鍵盤有效,鍵盤能與計算機正常通信;假定鍵盤數據可從作業系統傳輸到 Java 虛擬機,又從 Java 虛擬機傳輸 inputReader。
  大多數情況下上述假設都成立,但不盡然。為此,Java 採用異常方法,以應對可能出現的錯誤,並採取步驟進行更正。在本例中,若試圖編譯以上代碼,將看到以下信息:
  Exception in thread "main" java.lang.Error: Unresolved compilation problem:
  Unhandled exception type IOException
  at EchoInput.main(EchoInput.java:7)
  從中可以看到,第 7 行調用 readLine 方法可能出錯:若果真如此,則產生 IOException 來記錄故障。編譯器錯誤是在告訴您,需要更改代碼來解決這個潛在的問題。在 JDK API 文檔中,可以看到同樣的信息。我們可以看到 readLine 方法,如圖 1 所示。
  「捕獲 (catch)」指當 readLine 方法產生錯誤時截獲該錯誤,並處理和記錄該問題。而「聲明 (declare)」指錯誤可能引發 IOException,並通知調用該方法的任何代碼:可能產生異常。
  若要捕獲異常,必須添加一個特殊的「處理代碼塊」,來接收和處理 IOException。於是程序改為如下:
  1 import java.io.*;
  2 public class EchoInputHandle {
  3 public static void main(String args[]){
  4 System.out.println("Enter text to echo:");
  5 InputStreamReader isr = new InputStreamReader(System.in);
  6 BufferedReader inputReader = new BufferedReader(isr);
  7 try{
  8 String inputLine = inputReader.readLine();
  9 System.out.println("Read:" + inputLine);
  10 }
  11 catch(IOException exc){
  12 System.out.println(「Exception encountered: 」 + exc);
  13 }
  14 }
  15 }
  新添的代碼塊包含關鍵字 try 和 catch(第 7,10,11,13 行),表示要讀取輸入。若成功,則正常運行。若讀取輸入時錯誤,則捕獲問題(由 IOException 對象表示),並採取相應措施。在本例,採用的處理方式是輸出異常。
  若不準備捕獲 IOException,僅聲明異常,則要特別指定 main 方法可能出錯,而且特別說明可能產生 IOException。於是程序改為如下:
  1 import java.io.*;
  2 public class EchoInputDeclare {
  3 public static void main(String args[]) throws IOException{
  4 System.out.println("Enter text to echo:");
  5 InputStreamReader isr = new InputStreamReader(System.in);
  6 BufferedReader inputReader = new BufferedReader(isr);
  7 String inputLine = inputReader.readLine();
  8 System.out.println("Read:" + inputLine);
  9 }
  10 }
  從上面的這個簡單的例子中,我們可以看出異常處理在 Java 代碼開發中不能被忽視。
  Java 異常以及異常處理
  可將 Java 異常看作是一類消息,它傳送一些系統問題、故障及未按規定執行的動作的相關信息。異常包含信息,以將信息從應用程式的一部分發送到另一部分。
  編譯語言為何要處理異常?為何不在異常出現位置隨時處理具體故障?因為有時候我們需要在系統中交流錯誤消息,以便按照統一的方式處理問題,有時是因為有若干處理問題的可能方式,但您不知道使用哪一種,此時,可將處理異常的任務委託給調用方法的代碼。調用者通常更能了解問題來源的上下文,能更好的確定恢復方式。
  異常本身表示消息,指發送者傳給接收者的數據「負荷」。首先,異常基於類的類型來傳輸有用信息。很多情況下,基於異常的類既能識別故障本因並能更正問題。其次,異常還帶有可能有用的數據(如屬性)。
  在處理異常時,消息必須有接收者;否則將無法處理產生異常的底層問題。
  在上例中,異常「產生者」是讀取文本行的 BufferedReader。在故障出現時,將在 readLine 方法中構建 IOException 對象。異常「接收者」是代碼本身。EchoInputHandle 應用程式的 try-catch 結構中的 catch 塊是異常的接收者,它以字符串形式輸出異常,將問題記錄下來。
  Java 異常類的層次結構
  在我們從總體上了解異常後,我們應該了解如何在 Java 應用程式中使用異常,即需要了解 Java 類的層次結構。
  在 Java 中,所有的異常都有一個共同的祖先 Throwable(可拋出)。Throwable 指定代碼中可用異常傳播機制通過 Java 應用程式傳輸的任何問題的共性。
  Throwable 有兩個重要的子類:Exception(異常)和 Error(錯誤),二者都是 Java 異常處理的重要子類,各自都包含大量子類。
  Exception(異常)是應用程式中可能的可預測、可恢復問題。一般大多數異常表示中度到輕度的問題。異常一般是在特定環境下產生的,通常出現在代碼的特定方法和操作中。在 EchoInput 類中,當試圖調用 readLine 方法時,可能出現 IOException 異常。
  Error(錯誤)表示運行應用程式中較嚴重問題。大多數錯誤與代碼編寫者執行的操作無關,而表示代碼運行時 JVM(Java 虛擬機)出現的問題。例如,當 JVM 不再有繼續執行操作所需的內存資源時,將出現 OutOfMemoryError。
  Exception 類有一個重要的子類 RuntimeException。RuntimeException 類及其子類表示「JVM 常用操作」引發的錯誤。例如,若試圖使用空值對象引用、除數為零或數組越界,則分別引發運行時異常(NullPointerException、ArithmeticException)和 ArrayIndexOutOfBoundException。
  Java 異常的處理
  在 Java 應用程式中,對異常的處理有兩種方式:處理異常和聲明異常。
  處理異常:try、catch 和 finally
  若要捕獲異常,則必須在代碼中添加異常處理器塊。這種 Java 結構可能包含 3 個部分,
  都有 Java 關鍵字。下面的例子中使用了 try-catch-finally 代碼結構。
  1 import java.io.*;
  2 public class EchoInputTryCatchFinally {
  3 public static void main(String args[]){
  4 System.out.println("Enter text to echo:");
  5 InputStreamReader isr = new InputStreamReader(System.in);
  6 BufferedReader inputReader = new BufferedReader(isr);
  7 try{
  8 String inputLine = inputReader.readLine();
  9 System.out.println("Read:" + inputLine);
  10 }
  11 catch(IOException exc){
  12 System.out.println("Exception encountered: " + exc);
  13 }
  14 finally{
  15 System.out.println("End. ");
  16 }
  17 }
  18}
  其中:
  try 塊:將一個或者多個語句放入 try 時,則表示這些語句可能拋出異常。編譯器知道可能要發生異常,於是用一個特殊結構評估塊內所有語句。
  catch 塊:當問題出現時,一種選擇是定義代碼塊來處理問題,catch 塊的目的便在於此。catch 塊是 try 塊所產生異常的接收者。基本原理是:一旦生成異常,則 try 塊的執行中止,JVM 將查找相應的 JVM。
  finally 塊:還可以定義 finally 塊,無論運行 try 塊代碼的結果如何,該塊裡面的代碼一定運行。在常見的所有環境中,finally 塊都將運行。無論 try 塊是否運行完,無論是否產生異常,也無論是否在 catch 塊中得到處理,finally 塊都將執行。
  try-catch-finally 規則:
  必須在 try 之後添加 catch 或 finally 塊。try 塊後可同時接 catch 和 finally 塊,但至少有一個塊。
  必須遵循塊順序:若代碼同時使用 catch 和 finally 塊,則必須將 catch 塊放在 try 塊之後。
  catch 塊與相應的異常類的類型相關。
  一個 try 塊可能有多個 catch 塊。若如此,則執行第一個匹配塊。
  可嵌套 try-catch-finally 結構。
  在 try-catch-finally 結構中,可重新拋出異常。
  除了下列情況,總將執行 finally 做為結束:JVM 過早終止(調用 System.exit(int));在 finally 塊中拋出一個未處理的異常;計算機斷電、失火、或遭遇病毒攻擊。
  聲明異常
  若要聲明異常,則必須將其添加到方法簽名塊的結束位置。下面是一個實例:
  public void errorProneMethod(int input) throws java.io.IOException {
  //Code for the method,including one or more method
  //calls that may produce an IOException
  }
  這樣,聲明的異常將傳給方法調用者,而且也通知了編譯器:該方法的任何調用者必須遵守處理或聲明規則。聲明異常的規則如下:
  必須聲明方法可拋出的任何可檢測異常(checked exception)。
  非檢測性異常(unchecked exception)不是必須的,可聲明,也可不聲明。
  調用方法必須遵循任何可檢測異常的處理和聲明規則。若覆蓋一個方法,則不能聲明與覆蓋方法不同的異常。聲明的任何異常必須是被覆蓋方法所聲明異常的'同類或子類。
  Java 異常處理的分類
  Java 異常可分為可檢測異常,非檢測異常和自定義異常。
  可檢測異常
  可檢測異常經編譯器驗證,對於聲明拋出異常的任何方法,編譯器將強制執行處理或聲明規則,例如:sqlExecption 這個異常就是一個檢測異常。你連接 JDBC 時,不捕捉這個異常,編譯器就通不過,不允許編譯。
  非檢測異常
  非檢測異常不遵循處理或聲明規則。在產生此類異常時,不一定非要採取任何適當操作,編譯器不會檢查是否已解決了這樣一個異常。例如:一個數組為 3 個長度,當你使用下標為3時,就會產生數組下標越界異常。這個異常 JVM 不會進行檢測,要靠程式設計師來判斷。有兩個主要類定義非檢測異常:RuntimeException 和 Error。
  Error 子類屬於非檢測異常,因為無法預知它們的產生時間。若 Java 應用程式內存不足,則隨時可能出現 OutOfMemoryError;起因一般不是應用程式的特殊調用,而是 JVM 自身的問題。另外,Error 一般表示應用程式無法解決的嚴重問題。
  RuntimeException 類也屬於非檢測異常,因為普通 JVM 操作引發的運行時異常隨時可能發生,此類異常一般是由特定操作引發。但這些操作在 Java 應用程式中會頻繁出現。因此,它們不受編譯器檢查與處理或聲明規則的限制。
  自定義異常
  自定義異常是為了表示應用程式的一些錯誤類型,為代碼可能發生的一個或多個問題提供新含義。可以顯示代碼多個位置之間的錯誤的相似性,也可以區分代碼運行時可能出現的相似問題的一個或者多個錯誤,或給出應用程式中一組錯誤的特定含義。例如,對隊列進行操作時,有可能出現兩種情況:空隊列時試圖刪除一個元素;滿隊列時試圖添加一個元素。則需要自定義兩個異常來處理這兩種情況。
  Java 異常處理的原則和忌諱
  Java 異常處理的原則
  儘可能的處理異常
  要儘可能的處理異常,如果條件確實不允許,無法在自己的代碼中完成處理,就考慮聲明異常。如果人為避免在代碼中處理異常,僅作聲明,則是一種錯誤和依賴的實踐。
  具體問題具體解決
  異常的部分優點在於能為不同類型的問題提供不同的處理操作。有效異常處理的關鍵是識別特定故障場景,並開發解決此場景的特定相應行為。為了充分利用異常處理能力,需要為特定類型的問題構建特定的處理器塊。
  記錄可能影響應用程式運行的異常
  至少要採取一些永久的方式,記錄下可能影響應用程式操作的異常。理想情況下,當然是在第一時間解決引發異常的基本問題。不過,無論採用哪種處理操作,一般總應記錄下潛在的關鍵問題。別看這個操作很簡單,但它可以幫助您用很少的時間來跟蹤應用程式中複雜問題的起因。
  根據情形將異常轉化為業務上下文
  若要通知一個應用程式特有的問題,有必要將應用程式轉換為不同形式。若用業務特定狀態表示異常,則代碼更易維護。從某種意義上講,無論何時將異常傳到不同上下文(即另一技術層),都應將異常轉換為對新上下文有意義的形式。
  Java 異常處理的忌諱
  一般不要忽略異常
  在異常處理塊中,一項最危險的舉動是「不加通告」地處理異常。如下例所示:
  1 try{
  2 Class.forName("business.domain.Customer");
  3 }
  4 catch (ClassNotFoundException exc){}
  經常能夠在代碼塊中看到類似的代碼塊。有人總喜歡在編寫代碼時簡單快速地編寫空處理器塊,並「自我安慰地」宣稱準備在「後期」添加恢復代碼,但這個「後期」變成了「無期」。
  這種做法有什麼壞處?如果異常對應用程式的其他部分確實沒有任何負面影響,這未嘗不可。但事實往往並非如此,異常會擾亂應用程式的狀態。此時,這樣的代碼無異於掩耳盜鈴。
  這種做法若影響較輕,則應用程式可能出現怪異行為。例如,應用程式設置的一個值不見了, 或 GUI 失效。若問題嚴重,則應用程式可能會出現重大問題,因為異常未記錄原始故障點,難以處理,如重複的 NullPointerExceptions。
  如果採取措施,記錄了捕獲的異常,則不可能遇到這個問題。實際上,除非確認異常對代碼其餘部分絕無影響,至少也要作記錄。進一步講,永遠不要忽略問題;否則,風險很大,在後期會引發難以預料的後果。
  不要使用覆蓋式異常處理塊
  另一個危險的處理是覆蓋式處理器(blanket handler)。該代碼的基本結構如下:
  1 try{
  2 // …
  3 }
  4 catch(Exception e){
  5 // …
  6 }
  使用覆蓋式異常處理塊有兩個前提之一:
  1. 代碼中只有一類問題。
  這可能正確,但即便如此,也不應使用覆蓋式異常處理,捕獲更具體的異常形式有利物弊。
  2. 單個恢復操作始終適用。
  這幾乎絕對錯誤。幾乎沒有哪個方法能放之四海而皆準,能應對出現的任何問題。
  分析下這樣編寫代碼將發生的情況。只要方法不斷拋出預期的異常集,則一切正常。但是,如果拋出了未預料到的異常,則無法看到要採取的操作。當覆蓋式處理器對新異常類執行千篇一律的任務時,只能間接看到異常的處理結果。如果代碼沒有列印或記錄語句,則根本看不到結果。
  更糟糕的是,當代碼發生變化時,覆蓋式處理器將繼續作用於所有新異常類型,並以相同方式處理所有類型。
  一般不要把特定的異常轉化為更通用的異常
  將特定的異常轉換為更通用異常時一種錯誤做法。一般而言,這將取消異常起初拋出時產生的上下文,在將異常傳到系統的其他位置時,將更難處理。見下例:
  1 try{
  2 // Error-prone code
  3 }
  4 catch(IOException e){
  5 String msg = "If you didn 』 t have a problem before,you do now!";
  6 throw new Exception(msg);
  7 }
  因為沒有原始異常的信息,所以處理器塊無法確定問題的起因,也不知道如何更正問題。
  不要處理能夠避免的異常
  對於有些異常類型,實際上根本不必處理。通常運行時異常屬於此類範疇。在處理空指針或者數據索引等問題時,不必求助於異常處理。
  Java 異常處理的應用實例
  在定義銀行類時,若取錢數大於餘額時需要做異常處理。
  定義一個異常類 insufficientFundsException。取錢(withdrawal)方法中可能產生異常,條件是餘額小於取額。
  處理異常在調用 withdrawal 的時候,因此 withdrawal 方法要聲明拋出異常,由上一級方法調用。
  異常類:
  class InsufficientFundsExceptionextends Exception{
  private Bank excepbank; // 銀行對象
  private double excepAmount; // 要取的錢
  InsufficientFundsException(Bank ba, double dAmount)
  { excepbank=ba;
  excepAmount=dAmount;
  }
  public String excepMessage(){
  String str="The balance is"+excepbank.balance
  + " "+"The withdrawal was"+excepAmount;
  return str;
  }
  }// 異常類
  銀行類:
  class Bank{
  double balance;// 存款數
  Bank(double balance){this.balance=balance;}
  public void deposite(double dAmount){
  if(dAmount>0.0) balance+=dAmount;
  }
  public void withdrawal(double dAmount)
  throws InsufficientFundsException{
  if (balance
  InsufficientFundsException(this, dAmount);
  balance=balance-dAmount;
  }
  public void showBalance(){
  System.out.println("The balance is "+(int)balance);
  }
  }
  前端調用:
  public class ExceptionDemo{
  public static void main(String args[]){
  try{
  Bank ba=new Bank(50);
  ba.withdrawal(100);
  System.out.println("Withdrawal successful!");
  }catch(InsufficientFundsException e) {
  System.out.println(e.toString());
  System.out.println(e.excepMessage());
  }
  }
  }

收藏

相關推薦

清純唯美圖片大全

字典網 - 試題庫 - 元問答 - 简体 - 頂部

Copyright © cnj8 All Rights Reserved.