<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    中文JAVA技術(shù)平等自由協(xié)作創(chuàng)造

    Java專題文章博客和開源

    常用鏈接

    統(tǒng)計

    最新評論

    用Guava輔助Throwable異常處理

      Guava的 Throwables 工具常常可以讓exception處理更方便。
      Propagation
      有時候,你會想把捕獲的exception拋到上一個try/catch塊。對于 RuntimeException 和 Error 尤為如此,它們不需要 try/catch 塊,但可能被其他的 try/catch 塊無意捕獲。
      Guava 提供了一些工具來簡化propagate exception。例如:
      try{
      someMethodThatCouldThrowAnything();
      }catch(IKnowWhatToDoWithThisException e){
      handle(e);
      }catch(Throwable t){
      Throwables.propagateIfInstanceOf(t, IOException.class);
      Throwables.propagateIfInstanceOf(t, SQLException.class);
      throw Throwables.propagate(t);
      }
      這里的每個方法都會拋出它們自己的exception,但是throw最終結(jié)果 —— 如,throw Throwables.propagate(t) —— 對編譯檢查有指示作用,提示這里肯定會拋出一個exception。
      這里是Guava提供的propagation方法的簡單總結(jié):
      參數(shù)形式解釋
      RuntimeException propagate(Throwable)如果參數(shù)throwable是 RuntimeException 或 Error 則原樣propagate,否則將它包入 RuntimeException 中拋出。保證拋出。返回值是 RuntimeException 類型,因此你可以像上面那樣寫 throw Throwables.propagate(t) ,這樣Java編譯器會明白這一行肯定會拋出一個exception。
      void propagateIfInstanceOf(Throwable, Class) throws X僅當(dāng)參數(shù)throwable是 X 類型時,原樣propagate。
      void propagateIfPossible(Throwable)僅當(dāng)參數(shù)throwable是 RuntimeException 或 Error 類型時,原樣propagate。
      void propagateIfPossible(Throwable, Class) throws X僅當(dāng)參數(shù) throwable 是 RuntimeException 或 Error 或 X 類型時,原樣propagate。
      Throwables.propagate的用途 模仿Java 7的多重catch和重新throw
      一般來說,調(diào)用者如果想要讓exception沿著調(diào)用棧傳播,他只要不寫 catch 塊就可以了。既然他不打算在exception后恢復(fù),他恐怕也不需要寫入log或者采取什么其他行動。他可能需要進行一些清理工作,但是無論有沒有expction都會需要,因此清理工作會放在 finally 塊中。盡管如此,會重新throw的 catch 塊有時還是有意義的:也許調(diào)用者想要在傳播exception之前先更新崩潰計數(shù)器,或者他只想在特定條件下傳播exception。
      只有一種exception的時候,catch和重新throw是簡單直接的。麻煩的是有多種exception的時候:
      @Overridepublicvoid run(){
      try{
      delegate.run();
      }catch(RuntimeException e){
      failures.increment();
      throw e;
      }catch(Error e){
      failures.increment();
      throw e;
      }
      }
      Java 7用 multicatch 來解決這個問題:
      }catch(RuntimeException|Error e){
      failures.increment();
      throw e;
      }
      但不用Java 7的用戶就沒辦法了。他們也想寫如下的代碼,但編譯器不允許拋出Throwable類型的變量:
      }catch(Throwable t){
      failures.increment();
      throw t;
      }
      解決方案是用 throw Throwables.propagate(t) 來替換 throw t 。僅就這種情況而言, Throwables.propagate 跟之前代碼的功能完全相同。但是,代碼里寫 Throwables.propagate 很容易有一種隱藏的副作用。具體來說,要注意上面這種模式只適用于 RuntimeException 和 Error。如果 catch 塊可能捕捉checked exception,你還需要調(diào)用 propagateIfInstanceOf 來保證正常功能,因為 Throwables.propagate 無法直接傳播checked exception。
      總體來說,這種 propagate 的用法效果一般。在Java 7下沒必要這樣做。在其他版本的Java下,這樣能略微減少重復(fù),但是一個簡單的Extract Method重構(gòu)也可以達到同樣效果。另外,使用 propagate makes it easy to accidentally wrap checked exceptions.
      無用功:把 throws Throwable 轉(zhuǎn)化為 throws Exception
      某些API,尤其是Java reflection API 和 (相應(yīng)的) JUnit,有拋出 Throwable 的方法。運用這些API可能很麻煩,因為就算是最通用的API一般也只聲明throws Exception。 Throwables.propagate 是為非 Exception ,非 Error 的 Throwable 準備的。這個例子聲明了一個執(zhí)行JUnit測試的 Callable :
      public void call() throws Exception{
      try{
      FooTest.super.runTest();
      }catch(Throwable t){
      Throwables.propagateIfPossible(t,Exception.class);
      Throwables.propagate(t);
      }
      return null;
      }
      這里沒必要propagate(),并且第二行與="throw new RuntimeException(t)"等價。 (順便說一句:這個例子也提醒了我 propagateIfPossible 可能令人迷惑,因為它不僅傳播參數(shù)指定的類型,也傳播 Error 和 RuntimeException。)
      這種模式 (或者類似的寫法,如"throw new RuntimeException(t)") 在Google的代碼庫里至少出現(xiàn) 30 次。(搜索'propagateIfPossible[^;]* Exception.class[)];'試試。) 采用"throw new RuntimeException(t)"寫法的略占多數(shù)。我們也有可能想要一個"throwWrappingWeirdThrowable"方法來做Throwable到Exception的轉(zhuǎn)換,但是既然兩行就能搞定,這個方法還是沒有太大必要,除非我們要廢除propagateIfPossible方法。sat答案
      Throwables.propagate有爭議的用法 有爭議:把 checked exception 轉(zhuǎn)化為 unchecked exception
      理論上,unchecked exception表示有bug,checked exceptions表示在你控制范圍之外的問題。但在實踐上,即使JDK有時也會用錯 (至少,對于某些方法,沒有普遍認同的正確答案)。
      因此,有時調(diào)用者需要讓這兩種exception類型相互轉(zhuǎn)化:
      try{
      return Integer.parseInt(userInput);
      }catch(NumberFormatException e){
      throw new InvalidInputException(e);
      }
      try{
      return publicInterfaceMethod.invoke();
      }catch(IllegalAccessException e){
      throw new AssertionError(e);
      }
      有時候,這些調(diào)用者會用 Throwables.propagate 。有什么壞處呢?最主要的問題是代碼的含義不太明顯。throw Throwables.propagate(ioException) 有什么效果?throw new RuntimeException(ioException) 有什么效果?這兩行代碼功能是相同的,但后者更直白。前者使人生疑:"這是在做什么?應(yīng)該不只是打包成 RuntimeException 吧?如果只為這個,為何不寫一個wrapper方法呢?"只能承認,部分問題在于"propagate"這個名字很含糊。(它是一個拋出未聲明exception的方式嗎?) 也許換成"wrapIfChecked"會好一些。但即使叫這個名字,在已知checked exception上調(diào)用它也沒有什么優(yōu)勢。可能還會有副作用: 也許會有比普通 RuntimeException 更合適的拋出類型 -- 比如, IllegalArgumentException。
      我們有時也會看到在exception僅僅有可能是checked exception時用 propagate 。相對來說,這種做法后果小一些,也不那么直白:
      }catch(RuntimeException e){
      throw e;
      }catch(Exception e){
      throw new RuntimeException(e);
      }
      }catch(Exception e){
      throw Throwables.propagate(e);
      }
      盡管如此,這里不可忽視的問題在于將checked exception轉(zhuǎn)化為unchecked exception的行為本身。在某些情況下是無可厚非的,但更多的時候這樣做是在逃避對常規(guī) checked exception 的處理。這讓我們思考checked exception本身是否就是一個壞主意。我不想說得這么深入。姑且說 ,Throwables.propagate 不是讓 Java 使用者用來忽略 IOException 及類似異常的。
      有爭議: Exception隧道托福答案
      但是當(dāng)你實現(xiàn)一個不允許throw exception的方法時怎么辦呢?有時你需要把exception打包在unchecked exception中。這樣沒問題,但同樣的,對于單純的打包 propagate 沒有必要。事實上,自己實現(xiàn)打包會更好一些:如果你把每個exception(而不只是checked exception)打包,那就可以在另一端解包,減少特殊處理。另外,最好打包成自定義的exception類型。
      有爭議: 重新拋出其他線程的exception
      try{
      return future.get();
      }catch(ExecutionException e){
      throw Throwables.propagate(e.getCause());
      }
      這里有幾件要考慮的事:
      對于checked exception:參見上面的"把 checked exception 轉(zhuǎn)化為 unchecked exception"一節(jié)。但如果此處已知不會拋出checked exception呢? (也許是 Runnable 的結(jié)果。) 如上所述,你可以catch這個exception然后拋出 AssertionError ;propagate 沒有什么用。特別的是,對于Future,也可以考慮Futures.get。
      對于非Exception,非Error的Throwable。(好吧,這個可能性不大,但是如果你試圖直接重新throw它,編譯器會強迫你考慮這種可能) 參考上面的 "把 throws Throwable 轉(zhuǎn)化為 throws Exception" 一節(jié).
      對于unchecked exception或error。那么它會直接被重新throw。不幸的是,它的stack trace會顯示原先產(chǎn)生exception的線程,而不是當(dāng)前傳播到的線程。一般最好的結(jié)果是把兩個線程的stack trace都包括在exception chain中,就像 get 拋出的 ExecutionException 一樣。(這其實不是 propagate 的問題; 這是所有把 exception 在另一個線程拋出的共同問題。)
      因果鏈
      Guava讓研究一個exception的因果鏈(causal chain)更簡單了一些,它提供了以下3個很有用的方法,功能顧名思義:
      Throwable getRootCause(Throwable)
      List getCausalChain(Throwable)
      String getStackTraceAsString(Throwable)

    posted on 2014-09-20 14:52 好不容易 閱讀(592) 評論(0)  編輯  收藏


    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
     
    PK10開獎 PK10開獎
    主站蜘蛛池模板: 国产亚洲综合一区柠檬导航| 亚洲毛片基地日韩毛片基地| 一级毛片在线免费看| 小日子的在线观看免费| 久久狠狠爱亚洲综合影院| www.亚洲色图.com| 真人做A免费观看| h视频免费高清在线观看| 亚洲国产a级视频| 亚洲美女视频免费| 亚洲视频在线免费| 亚洲a级成人片在线观看| 美腿丝袜亚洲综合| 在线观看免费视频一区| 中文字幕亚洲码在线| 久久久久亚洲AV片无码| 又大又黄又粗又爽的免费视频| 中文字幕乱码亚洲精品一区| 亚洲乱亚洲乱妇无码麻豆| 女人张开腿等男人桶免费视频| 在线观看肉片AV网站免费| 无码久久精品国产亚洲Av影片| 大陆一级毛片免费视频观看 | 亚洲成aⅴ人片在线影院八| 四虎永久免费网站免费观看| 8x8×在线永久免费视频| 一级一级一级毛片免费毛片| 亚洲色精品三区二区一区| 亚洲综合日韩中文字幕v在线| 国产人成免费视频网站| 在线免费播放一级毛片| 国产成人高清亚洲一区91| youjizz亚洲| 777亚洲精品乱码久久久久久| 久久亚洲2019中文字幕| 在线观看亚洲免费视频| 亚洲欧洲免费无码| 成年人网站免费视频| 91精品免费观看| 日本亚洲欧洲免费天堂午夜看片女人员 | 日本高清免费中文在线看|