簡略談談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給我們供給的異常機制,它宛如彷佛一個長者,時不時給我們指引途徑,也讓我們在編碼的時刻沒有那末無聊:)