1. 程式人生 > 程式設計 >JAVA基礎--如何通過異常處理錯誤

JAVA基礎--如何通過異常處理錯誤

《Thinking in Java》上對這章的講解不少,可見重要性,學習和總結一些主要的記錄下來。

一、建立自定義異常

package Exception; 
 class SimpleException extends Exception{}
 
 public class InheritingException{
  
  public void f() throws SimpleException {
   System.out.println("Throw SimpleException from f()");
   throw new SimpleException();
  }
  
  public static void main(String[] args) {
   InheritingException sed = new InheritingException();
   try {
    sed.f();
   } catch (SimpleException e) {
    e.printStackTrace();
   }
  }
  
 }

輸出:

Throw SimpleException from f()
Exception.SimpleException
at Exception.InheritingException.f(InheritingException.java:10)
at Exception.InheritingException.main(InheritingException.java:19)

  throw與throws的區別與詳情

  編譯器建立了預設構造器,它將自動呼叫基類的預設構造器。

  對異常來說,最重要的部分就是類名,其它也沒用,可以增加一個帶參的構造方法。

  比如NullPointerException:

 public class NullPointerException extends RuntimeException {
  private static final long serialVersionUID = 5162710183389028792L;
 
  /**
  * Constructs a {@code NullPointerException} with no detail message.
  */
  public NullPointerException() {
   super();
 }

  /**
  * Constructs a {@code NullPointerException} with the specified
   * detail message.
  *
  * @param s the detail message.
  */
  public NullPointerException(String s) {
   super(s);
  }
 }

二、捕獲異常

  1)try塊

    如果在方法內部丟擲了異常(或者在方法內部呼叫的其他方法丟擲了異常),這個方法將在丟擲異常的過程中結束。

    要是不希望方法就此結束,可以在方法內設定一個特殊的塊來捕獲異常。

try{
 //exceptions 
}

  2)異常處理程式

    異常處理程式緊跟在try塊之後,以關鍵字catch表示:

try{
 //exceptions 
} catch(Type1 id1) {
 //Type1 
} catch(Type2 id2) {
 //Type2
}

    當異常被丟擲時,異常處理機制將負責搜尋引數與異常型別相匹配的第一個處理程式。然後進入catch子句執行,此時認為異常得到了處理。

    注意,只有匹配的catch子句才能得到執行,這與switch語句不同。

  3)棧軌跡

    printStackTrace()方法所提供的資訊可以通過getStackTrace()方法來直接訪問,這個方法將返回一個由棧軌跡中的元素所構成的陣列,其中每一個元素都表示

  棧中的一幀。元素0是棧頂元素,並且是呼叫序列中的最後一個方法呼叫。陣列中最後一個元素和棧底是呼叫序列中的第一個方法呼叫。

 public class WhoCalled {
  static void f() {
   try {
    throw new Exception();
   } catch (Exception e) {
    for(StackTraceElement ste : e.getStackTrace()) {
     System.out.println("line: " + ste.getLineNumber() + " method: " + ste.getMethodName());
    }
   }
  }
  static void g() {f();}
  static void h() {g();}
  public static void main(String[] args) {f();g();h();}
 }

  程式輸出:

line: 5 method: f
line: 14 method: main
line: 5 method: f
line: 12 method: g
line: 14 method: main
line: 5 method: f
line: 12 method: g
line: 13 method: h
line: 14 method: main

三、Java標準異常

  Throwable這個Java類被用來表示任何可以作為異常被丟擲的類。

  Throwable物件可分為兩種型別:

1 Error用來表示編譯時和系統錯誤。

2 Exception是可以被丟擲的基本型別,程式設計師關心的基型別通常是Exception。

四、RuntimeException

if(t == null) {
 throw new NullPointerException(); 
}

  如果對Null引用進行呼叫,Java會自動丟擲NullPointerException異常,所以上述程式碼是多餘的,它屬於Java的標準執行時檢測的一部分:

public class NeverCaught {
  static void f() {
   throw new RuntimeException();
  }
  static void g() {f();}
  public static void main(String[] args) {
   g();
  }
 }

輸出:

Exception in thread "main" java.lang.RuntimeException

at Exception.NeverCaught.f(NeverCaught.java:6)

at Exception.NeverCaught.g(NeverCaught.java:10)

at Exception.NeverCaught.main(NeverCaught.java:14)

  從輸出可以發現,RuntimeException是一個特例,對於這種異常型別,編譯器不需要異常說明,其輸出被報告給了System.err。

  如果RuntimeException沒有被捕獲而直達main(),那麼在程式退出前將呼叫異常的printStackTrace()方法。

  *注意:

    只能在程式碼中忽略RuntimeException(及其子類)型別的異常,其它異常型別的處理都是由編譯器強制實施的。

  1)常見的五種RuntimeException

NullPointerException - 空指標引用異常

ClassCastException - 型別強制轉換異常

IllegalArgumentException - 傳遞非法引數異常

ArithmeticException - 算術運算異常

ArrayStoreException - 向陣列中存放與宣告型別不相容物件異常

IndexOutOfBoundsException - 下標越界異常

NegativeArraySizeException - 建立一個大小為負數的陣列錯誤異常

NumberFormatException - 數字格式異常

SecurityException - 安全異常

UnsupportedOperationException - 不支援的操作異常

五、使用finally進行清理

 class ThreeException extends Exception {}
 public class FinallyWorks {
  static int count = 0;
  public static void main(String[] args) {
   while(true) {
    try {
     if(count++ == 0) {
      throw new ThreeException();
     }
     System.out.println("No exception");
    } catch (ThreeException e) {
     System.out.println("ThreeException");
    } finally {
     System.out.println("In finally clause");
     if(count == 2) 
      break;
    }
   }
  }
 }

  這個程式給了我們一些思路(確實。。),如果把try塊放在迴圈裡,就建立了一個“程式繼續執行之前必須要到達”的條件。

  還可以加入一個static型別的計數器或者別的裝置,使迴圈在放棄之前能夠嘗試一定的次數。這將使程式的健壯性更上一個臺階(好叼的樣子)。

  1)finally用來做什麼

    當要把除記憶體之外的資源恢復到它們的初始狀態時,就要用到finally子句。

  2)在return中使用finally

    因為finally子句總是會執行的,所以在一個方法中,可以從多個點返回,並且可以保證重要的清理工作仍舊會執行:

class ThreeException extends Exception {}
 public class FinallyWorks {
  static int count = 0;
  public static void main(String[] args) {
   while(true) {
    try {
     if(count++ == 0) {
      throw new ThreeException();
     }
     System.out.println("No exception");
     return;
    } catch (ThreeException e) {
     System.out.println("ThreeException");
    } finally {
     System.out.println("In finally clause");
     if(count == 3) 
      break;
    }
   }
  }
 }

第一次迴圈,首先執行第7行,符合條件,丟擲異常,執行catch塊,最後執行finally清理,不符合第16行判斷,繼續迴圈

第二次迴圈,不符合第7行判斷,丟擲異常,並return,但依舊執行finally清理,不符合第16行判斷,但try塊中已經執行return,所以程式結束,輸出:

ThreeException
In finally clause
No exception
In finally clause

  3)Java異常的缺憾:異常丟失

 public class ExceptionSilencer {
  public static void main(String[] args) {
  try {
    throw new RuntimeException();
   } finally {
    return;
   }
  }
 }

以上就是JAVA基礎--如何通過異常處理錯誤的詳細內容,更多關於JAVA 通過異常處理錯誤的資料請關注我們其它相關文章!