程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 簡略談談java的異常處置(Try Catch Finally)

簡略談談java的異常處置(Try Catch Finally)

編輯:關於JAVA

簡略談談java的異常處置(Try Catch Finally)。本站提示廣大學習愛好者:(簡略談談java的異常處置(Try Catch Finally))文章只能為提供參考,不一定能成為您想要的結果。以下是簡略談談java的異常處置(Try Catch Finally)正文


異常的英文單詞是exception,字面翻譯就是“不測、破例”的意思,也就長短正常情形。現實上,異常實質上是法式上的毛病,包含法式邏輯毛病和體系毛病。

一 媒介

java異常處置年夜家都不生疏,總的來講有上面兩點:

1.拋出異常:throw exception

class SimpleException{
  public void a() throws Exception{
    throw new Exception();
  };
}

2.捕捉異常:

public class MyException {
  public static void main(String[] args){
    MyException e = new MyException();
    SimpleException se = new SimpleException();
    try {
      se.a();
    } catch (Exception e1) {
      e1.printStackTrace();
    }
  }
}

class SimpleException{
  public void a() throws Exception{
    throw new Exception();
  };
}

本文將在此基本上,加倍深刻的談一些細節成績。

二 自界說異常類

java說話為我們供給了許多異常類,然則有時刻我們為了寫代碼的便利照樣要自界說的去發明異常類:

class SimpleException extends Exception {};
創立好以後我們可使用try catch捕捉它:

public class MyException {
  public static void main(String[] args){
    MyException e = new MyException();
    try {
      e.a();
    } catch (SimpleException e1) {
      e1.printStackTrace();
    }
  }
  
  public void a() throws SimpleException{
    throw new SimpleException();
  }
}

class SimpleException extends Exception {};

我們在MyException中界說了一個辦法a(),讓它拋出SimpleException異常,然後我們在main()中挪用這個辦法,並應用try catch捕捉了這個異常:

SimpleException
  at MyException.a(MyException.java:15)
  at MyException.main(MyException.java:8)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:606)
  at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

Process finished with exit code 0


編譯履行後的成果,重要看前三行就好了。這裡側重解釋幾點:
1.拋出異常類型的指定:(exception specification)
當我們須要在一個辦法中拋出一個異常時,我們應用throw後加某異常類的實例,法式會在此向客戶端法式(挪用這段代碼的法式)拋出對應異常並在此加入(相當於return)。別的須要留意的是,我們必需在界說該辦法的時刻指明異常類型,好比上面這段代碼會拋出SimpleException異常

public void a() throws SimpleException

2.拋出多個異常:

  public void a() throws SimpleException,AException,BException{
    throw new SimpleException();
    
  }

分歧的異常類之間用逗號離隔便可,在這類情形下我們不用須throw每一個異常類的實例(),然則客戶端代碼必需要catch到每一個異常類:

public class MyException {
  public static void main(String[] args){
    MyException e = new MyException();
    try {
      e.a();
    } catch (SimpleException e1) {
      e1.printStackTrace();
    } catch (BException e1) {
      e1.printStackTrace();
    } catch (AException e1) {
      e1.printStackTrace();
    }
  }

  public void a() throws SimpleException,AException,BException{
    throw new SimpleException();
    
  }
}

class SimpleException extends Exception {};
class AException extends Exception{}
class BException extends Exception{}


三 stack trace

不管是拋出異常,或許是捕捉處置異常,我們的目標是為了寫出更硬朗的法式,這很年夜水平上依附於java異常機制給我們供給的異常信息,而它的載體就是stack trace。
後面的代碼中我們直接應用printStackTrace()打印出異常信息,其實我們還可使用getStackTrace()辦法來獲得StackTraceElement型的聚集,假如你手頭有IDEA的話,你可以先搜刮出StackTraceElement類,可以發明它完成了接口Serializable ,再看看它的類描寫:

/**
 * An element in a stack trace, as returned by {@link
 * Throwable#getStackTrace()}. Each element represents a single stack frame.
 * All stack frames except for the one at the top of the stack represent
 * a method invocation. The frame at the top of the stack represents the
 * execution point at which the stack trace was generated. Typically,
 * this is the point at which the throwable corresponding to the stack trace
 * was created.
 *
 * @since 1.4
 * @author Josh Bloch
 */

講的很清晰,這個類的每一個實例都是stack trace的一個元素,代表著一個stack frame,stack trace是由getStackTrace()辦法前往的。後邊的我試著翻譯了幾遍,都認為欠好,照樣直接上代碼能力說清晰:

public class MyException {
  public static void main(String[] args){
    MyException e = new MyException();
    e.a();

  public void a(){
    try {
      throw new Exception();
    } catch (Exception e) {
      StackTraceElement[] ste = e.getStackTrace();
      System.out.println(ste.length);

    }
  }
}

我們界說了辦法a,讓它拋出Exception異常的同時捕捉它,然後我們經由過程getStackTrace()辦法獲得一個StackTraceElement型的數組,並打印出數組的長度:

7

Process finished with exit code 0
我們把代碼略微改一下,不在a中捕捉異常了,我們從新界說一個辦法b,讓它在挪用a的同時將異常捕捉:

public class MyException {
  public static void main(String[] args){
    MyException e = new MyException();
    e.b();
  }

  public void b(){
    try {
      a();
    } catch (Exception e) {
      StackTraceElement[] ste = e.getStackTrace();
      System.out.println(ste.length);
    }
  }

  public void a() throws Exception{
    throw new Exception();
  }
}

成果以下:

8

Process finished with exit code 0
別急,我們再來看點風趣的:

public class MyException {
  public static void main(String[] args){
    MyException exception = new MyException();
    try {
      exception.c();
    } catch (Exception e) {
      StackTraceElement[] ste = e.getStackTrace();
      System.out.println(ste.length);
      System.out.println("---------------------------------------------------------------");
      for (StackTraceElement s : e.getStackTrace()){
        System.out.println(s.getClassName()+":method "+s.getMethodName()+" at line"+s.getLineNumber());
      }
      System.out.println("---------------------------------------------------------------");

    }

  }

 public void c() throws Exception{
    try {
      a();
    }catch (Exception e){
      throw e;
    }
  }

  public void a() throws Exception{
    throw new Exception();
  }
}

上面是成果:

8
---------------------------------------------------------------
MyException:method a at line43
MyException:method c at line39
MyException:method main at line9
sun.reflect.NativeMethodAccessorImpl:method invoke0 at line-2
sun.reflect.NativeMethodAccessorImpl:method invoke at line57
sun.reflect.DelegatingMethodAccessorImpl:method invoke at line43
java.lang.reflect.Method:method invoke at line606
com.intellij.rt.execution.application.AppMain:method main at line144
---------------------------------------------------------------

Process finished with exit code 0

也就是說,getStackTrace()前往一個棧,它包括從挪用者(main())到初始拋出異常者(a())的一些根本信息 ,在下面的代碼中,我們在c辦法中挪用a辦法時捕捉異常並經由過程throws將其再次拋出(rethrow),挪用c辦法的辦法可以捕捉並處置異常,也能夠選擇持續拋出讓更高條理的挪用者(接近棧底)處置。rethrow固然很便利,但存在著一些成績,我們看上面這段代碼:

public class MyException {
  public static void main(String[] args){
    MyException exception = new MyException();
    try {
      exception.c();
    } catch (Exception e) {
      e.printStackTrace(System.out);
    }

  }

  public void c() throws Exception{
    try {
      a();
    }catch (Exception e){
      throw e;
    }
  }

  public void a() throws Exception{

    throw new Exception("Exception from a()");
  }
}
java.lang.Exception: Exception from a()
  at MyException.a(MyException.java:40)
  at MyException.c(MyException.java:30)
  at MyException.main(MyException.java:21)

我們在c中從新拋出e,在main中應用 e.printStackTrace()打印出來,可以看到打印出來stack trace照樣屬於a的,假如我們想把stack trace釀成c的可以這麼寫:

public class MyException {
  public static void main(String[] args){
    MyException exception = new MyException();

    try {
      exception.c();
    } catch (Exception e) {
      e.printStackTrace(System.out);
    }

  }

  public void c() throws Exception{
    try {
      a();
    }catch (Exception e){
//      throw e;
      throw (Exception)e.fillInStackTrace();
    }
  }

  public void a() throws Exception{

    throw new Exception("Exception from a()");
  }
}
java.lang.Exception: Exception from a()
  at MyException.c(MyException.java:22)
  at MyException.main(MyException.java:10)


四 異常鏈 Exception chaining

先來看一個場景:

public class TestException {
  public static void main(String[] args){
    TestException testException = new TestException();
    try {
      testException.c();
    } catch (CException e) {
      e.printStackTrace();
    }
  }

  public void a() throws AException{
    AException aException = new AException("this is a exception");
    throw aException;
  }

  public void b() throws BException{
    try {
      a();
    } catch (AException e) {
      throw new BException("this is b exception");
    }
  }

  public void c() throws CException{
    try {
      b();
    } catch (BException e) {
      throw new CException("this is c exception");
    }
  }
}

class AException extends Exception{
  public AException(String msg){
    super(msg);
  }
}

class BException extends Exception{
  public BException(String msg){
    super(msg);
  }
}

class CException extends Exception{
  public CException(String msg){
    super(msg);
  }
}

創立了三個異常類AException、BException、CException,然後在a()中拋出AException,在b()中捕捉AException並拋出BException,最初在c()中捕捉BException並拋出CException,成果打印以下:

CException: this is c exception
  at TestException.c(TestException.java:31)
  at TestException.main(TestException.java:8)

好,我們只看到了CException的信息,AException,BException的異常信息已喪失,這時候候異常鏈的感化就出來了,看代碼:

public class TestException {
  public static void main(String[] args){
    TestException testException = new TestException();
    try {
      testException.c();
    } catch (CException e) {
      e.printStackTrace();
    }
  }

  public void a() throws AException{
    AException aException = new AException("this is a exception");
    throw aException;
  }

  public void b() throws BException{
    try {
      a();
    } catch (AException e) {
//      throw new BException("this is b exception");
      BException bException = new BException("this is b exception");
      bException.initCause(e);
      throw bException;
    }
  }

  public void c() throws CException{
    try {
      b();
    } catch (BException e) {
//      throw new CException("this is c exception");
      CException cException = new CException("this is c exception");
      cException.initCause(e);
      throw cException;
    }
  }
}

class AException extends Exception{
  public AException(String msg){
    super(msg);
  }
}

class BException extends Exception{
  public BException(String msg){
    super(msg);
  }
}

class CException extends Exception{
  public CException(String msg){
    super(msg);
  }
}

我們用initCause()辦法將異常信息給串連了起來,成果以下:

CException: this is c exception
  at TestException.c(TestException.java:35)
  at TestException.main(TestException.java:8)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:606)
  at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: BException: this is b exception
  at TestException.b(TestException.java:24)
  at TestException.c(TestException.java:32)
  ... 6 more
Caused by: AException: this is a exception
  at TestException.a(TestException.java:15)
  at TestException.b(TestException.java:21)
  ... 7 more

Process finished with exit code 0


五 跋文

其實關於java異常處置還有許多須要商量的處所,然則因為我經歷無限,還不克不及領會的太深入,最經常使用的也就是

try {
      ...
    }catch (Exception e){
      ... 
    }finally {
     //不論異常會不會被捕獲或許處置都邑履行的代碼,如封閉IO操作 
    }

然則不管若何我們照樣要感激java給我們供給的異常機制,它宛如彷佛一個長者,時不時給我們指引途徑,也讓我們在編碼的時刻沒有那末無聊:)

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved