最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

簡(jiǎn)單談?wù)刯ava的異常處理(Try Catch Finally)

 更新時(shí)間:2016年03月26日 11:06:11   投稿:hebedich  
在程序設(shè)計(jì)中,進(jìn)行異常處理是非常關(guān)鍵和重要的一部分。一個(gè)程序的異常處理框架的好壞直接影響到整個(gè)項(xiàng)目的代碼質(zhì)量以及后期維護(hù)成本和難度。

異常的英文單詞是exception,字面翻譯就是“意外、例外”的意思,也就是非正常情況。事實(shí)上,異常本質(zhì)上是程序上的錯(cuò)誤,包括程序邏輯錯(cuò)誤和系統(tǒng)錯(cuò)誤。

一 前言

java異常處理大家都不陌生,總的來(lái)說(shuō)有下面兩點(diǎn):

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();
  };
}

本文將在此基礎(chǔ)上,更加深入的談一些細(xì)節(jié)問(wèn)題。

二 自定義異常類

java語(yǔ)言為我們提供了很多異常類,但是有時(shí)候我們?yōu)榱藢懘a的方便還是要自定義的去創(chuàng)造異常類:

class SimpleException extends Exception {};
創(chuàng)建好之后我們可以使用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 {};

我們?cè)贛yException中定義了一個(gè)方法a(),讓它拋出SimpleException異常,然后我們?cè)趍ain()中調(diào)用這個(gè)方法,并使用try catch捕獲了這個(gè)異常:

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


編譯執(zhí)行后的結(jié)果,主要看前三行就行了。這里著重說(shuō)明幾點(diǎn):
1.拋出異常類型的指定:(exception specification)
當(dāng)我們需要在一個(gè)方法中拋出一個(gè)異常時(shí),我們使用throw后加某異常類的實(shí)例,程序會(huì)在此向客戶端程序(調(diào)用這段代碼的程序)拋出對(duì)應(yīng)異常并在此退出(相當(dāng)于return)。另外需要注意的是,我們必須在定義該方法的時(shí)候指明異常類型,比如下面這段代碼會(huì)拋出SimpleException異常

public void a() throws SimpleException

2.拋出多個(gè)異常:

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

不同的異常類之間用逗號(hào)隔開(kāi)即可,在這種情況下我們不必須throw每個(gè)異常類的實(shí)例(),但是客戶端代碼必須要catch到每個(gè)異常類:

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

無(wú)論是拋出異常,或者是捕獲處理異常,我們的目的是為了寫出更健壯的程序,這很大程度上依賴于java異常機(jī)制給我們提供的異常信息,而它的載體就是stack trace。
前面的代碼中我們直接使用printStackTrace()打印出異常信息,其實(shí)我們還可以使用getStackTrace()方法來(lái)獲取StackTraceElement型的集合,如果你手頭有IDEA的話,你可以先搜索出StackTraceElement類,可以發(fā)現(xiàn)它實(shí)現(xiàn)了接口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
 */

講的很清楚,這個(gè)類的每個(gè)實(shí)例都是stack trace的一個(gè)元素,代表著一個(gè)stack frame,stack trace是由getStackTrace()方法返回的。后邊的我試著翻譯了幾遍,都覺(jué)得不好,還是直接上代碼才能說(shuō)清楚:

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異常的同時(shí)捕獲它,然后我們通過(guò)getStackTrace()方法得到一個(gè)StackTraceElement型的數(shù)組,并打印出數(shù)組的長(zhǎng)度:

7

Process finished with exit code 0
我們把代碼稍微改一下,不在a中捕獲異常了,我們重新定義一個(gè)方法b,讓它在調(diào)用a的同時(shí)將異常捕獲:

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();
  }
}

結(jié)果如下:

8

Process finished with exit code 0
別急,我們?cè)賮?lái)看點(diǎn)有趣的:

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();
  }
}

下面是結(jié)果:

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

也就是說(shuō),getStackTrace()返回一個(gè)棧,它包含從調(diào)用者(main())到初始拋出異常者(a())的一些基本信息 ,在上面的代碼中,我們?cè)赾方法中調(diào)用a方法時(shí)捕獲異常并通過(guò)throws將其再次拋出(rethrow),調(diào)用c方法的方法可以捕獲并處理異常,也可以選擇繼續(xù)拋出讓更高層次的調(diào)用者(靠近棧底)處理。rethrow雖然很方便,但存在著一些問(wèn)題,我們看下面這段代碼:

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()打印出來(lái),可以看到打印出來(lái)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

先來(lái)看一個(gè)場(chǎng)景:

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);
  }
}

創(chuàng)建了三個(gè)異常類AException、BException、CException,然后在a()中拋出AException,在b()中捕獲AException并拋出BException,最后在c()中捕獲BException并拋出CException,結(jié)果打印如下:

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

好,我們只看到了CException的信息,AException,BException的異常信息已丟失,這時(shí)候異常鏈的作用就出來(lái)了,看代碼:

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()方法將異常信息給串聯(lián)了起來(lái),結(jié)果如下:

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


五 后記

其實(shí)關(guān)于java異常處理還有很多需要探討的地方,但是由于我經(jīng)驗(yàn)有限,還不能體會(huì)的太深刻,最常用的也就是

try {
      ...
    }catch (Exception e){
      ... 
    }finally {
     //不管異常會(huì)不會(huì)被捕捉或者處理都會(huì)執(zhí)行的代碼,如關(guān)閉IO操作 
    }

但是無(wú)論如何我們還是要感謝java給我們提供的異常機(jī)制,它好似一個(gè)長(zhǎng)者,時(shí)不時(shí)給我們指引道路,也讓我們?cè)诰幋a的時(shí)候沒(méi)有那么無(wú)聊:)

相關(guān)文章

  • 解析Java8 Stream原理

    解析Java8 Stream原理

    說(shuō)起 Java 8,我們知道 Java 8 大改動(dòng)之一就是增加函數(shù)式編程,而 Stream API 便是函數(shù)編程的主角,Stream API 是一種流式的處理數(shù)據(jù)風(fēng)格,也就是將要處理的數(shù)據(jù)當(dāng)作流,在管道中進(jìn)行傳輸,并在管道中的每個(gè)節(jié)點(diǎn)對(duì)數(shù)據(jù)進(jìn)行處理,如過(guò)濾、排序、轉(zhuǎn)換等
    2021-06-06
  • 簡(jiǎn)單實(shí)現(xiàn)Java web服務(wù)器

    簡(jiǎn)單實(shí)現(xiàn)Java web服務(wù)器

    這篇文章主要為大家詳細(xì)介紹了簡(jiǎn)單實(shí)現(xiàn)Java web服務(wù)器的詳細(xì)步驟,感興趣的小伙伴們可以參考一下
    2016-06-06
  • JavaWeb文件上傳流程

    JavaWeb文件上傳流程

    這篇文章主要介紹了JavaWeb文件上傳流程,JavaWeb中最重要的技術(shù)之一,下文關(guān)于其文件上傳的流程分享,需要的小伙伴可以參考一下
    2022-05-05
  • Java 5個(gè)人坐在一起(有關(guān)第五個(gè)人歲數(shù)的問(wèn)題)

    Java 5個(gè)人坐在一起(有關(guān)第五個(gè)人歲數(shù)的問(wèn)題)

    利用遞歸的方法,遞歸分為回推和遞推兩個(gè)階段。要想知道第五個(gè)人歲數(shù),需知道第四人的歲數(shù),依次類推,推到第一人(10歲),再往回推,需要的朋友可以參考下
    2017-02-02
  • SpringBoot 統(tǒng)一異常處理的實(shí)現(xiàn)示例

    SpringBoot 統(tǒng)一異常處理的實(shí)現(xiàn)示例

    本文主要介紹了SpringBoot 統(tǒng)一異常處理的實(shí)現(xiàn)示例,目的就是在異常發(fā)生時(shí),盡可能地減少破壞,下面就來(lái)介紹一下,感興趣的可以了解一下
    2024-07-07
  • Java讀取文本文件的各種方法

    Java讀取文本文件的各種方法

    這篇文章主要介紹了Java讀取文本文件的各種方法,在 Java 中有多種方法可以讀取純文本文件,例如你可以使用FileReader、BufferedReader或Scanner來(lái)讀取文本文件,感興趣的小伙伴和小編一起進(jìn)入文章了解更多內(nèi)容吧,希望能幫助到大家
    2021-11-11
  • Jenkins Pipeline為Kubernetes應(yīng)用部署增加狀態(tài)檢測(cè)腳本優(yōu)化

    Jenkins Pipeline為Kubernetes應(yīng)用部署增加狀態(tài)檢測(cè)腳本優(yōu)化

    這篇文章主要為大家介紹了Jenkins Pipeline為Kubernetes應(yīng)用部署增加狀態(tài)檢測(cè)腳本優(yōu)化示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • redis防止重復(fù)提交的實(shí)現(xiàn)示例

    redis防止重復(fù)提交的實(shí)現(xiàn)示例

    在開(kāi)發(fā)中我們都需要處理重復(fù)提交的問(wèn)題,本文主要介紹了redis防止重復(fù)提交的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-06-06
  • Java 解析XML數(shù)據(jù)的4種方式

    Java 解析XML數(shù)據(jù)的4種方式

    這篇文章主要介紹了Java 解析XML數(shù)據(jù)的4種方式,幫助大家更好的用Java處理數(shù)據(jù),感興趣的朋友可以了解下
    2020-09-09
  • Java中的jinfo命令使用詳解

    Java中的jinfo命令使用詳解

    jinfo是JDK提供的一個(gè)可以實(shí)時(shí)查看Java虛擬機(jī)各種配置參數(shù)和系統(tǒng)屬性的命令行工具,本文給大家介紹下Java中的jinfo命令使用,感興趣的朋友一起看看吧
    2022-03-03

最新評(píng)論

深圳市| 水富县| 定陶县| 寿阳县| 渝北区| 梁平县| 旺苍县| 南通市| 旺苍县| 广饶县| 新营市| 都江堰市| 泰和县| 广饶县| 衡东县| 南安市| 东乡族自治县| 教育| 宜昌市| 浪卡子县| 乐东| 漳浦县| 遂昌县| 全州县| 泾阳县| 阿勒泰市| 盱眙县| 遂川县| 济源市| 临颍县| 青神县| 大方县| 泉州市| 安塞县| 柳江县| 德格县| 沾化县| 上虞市| 西城区| 富民县| 科技|