<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專題文章博客和開(kāi)源

    常用鏈接

    統(tǒng)計(jì)

    最新評(píng)論

    用Guava輔助Throwable異常處理

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

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


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


    網(wǎng)站導(dǎo)航:
     
    PK10開(kāi)獎(jiǎng) PK10開(kāi)獎(jiǎng)
    主站蜘蛛池模板: 亚洲国产免费综合| 午夜无遮挡羞羞漫画免费| 亚洲 另类 无码 在线| 亚洲一区二区三区高清在线观看 | 一本久久免费视频| 四虎永久在线精品免费影视 | 精品一区二区三区免费视频| 亚洲高清免费视频| 亚欧国产一级在线免费| 精品亚洲一区二区三区在线观看| www.av在线免费观看| 在线亚洲人成电影网站色www| 四虎国产精品永免费| 亚洲无线一二三四区手机| 一级有奶水毛片免费看| 亚洲级αV无码毛片久久精品| 免费播放在线日本感人片| 亚洲av福利无码无一区二区| 91高清免费国产自产拍2021| 亚洲成a人片在线观看中文app| 无码人妻一区二区三区免费| 亚洲第一区二区快射影院| 国产精品另类激情久久久免费| 成人午夜影视全部免费看| 亚洲av无码一区二区三区乱子伦| 四虎影视在线影院在线观看免费视频 | 51在线视频免费观看视频| 亚洲人成电影在线观看网| 四虎影视www四虎免费| 一级做a爰黑人又硬又粗免费看51社区国产精品视 | 久久精品人成免费| 亚洲一区二区三区在线| 国产精品国产免费无码专区不卡| a级毛片免费观看网站| 亚洲自偷精品视频自拍| 在线免费观看一级毛片| 国产精品九九久久免费视频| 亚洲大片在线观看| 成人免费毛片观看| 久久高潮一级毛片免费| 麻豆亚洲AV永久无码精品久久 |