暫無

          暫無
          posts - 3, comments - 0, trackbacks - 0, articles - 0
          很多事情都可以總結為WWWH問題。也就是What When Why & How。java異常恰巧是其中之一。


          首先,java的異常是什么?拋去官方冗長的定義,我覺得異常或者說exception,其實可以理解為這樣一句話:“wow!!這可不是我期待的狀態”。


          如果這樣理解異常,那么對于何時使用異常也就再清楚不過了。那就是,只有當出現了不在正常流程之中的某種狀態,這個時候就應該使用異常了。比如連接超時、傳入的參數為null或者數據無法插入到數據庫。


          那么,為什么我們要使用異常呢?理由其實很簡單,為了更加簡潔的代碼或者說為了OO。如果java沒有異常,我們會怎么處理呢?
          if(aMethod() == -1 )
          {
          //do someting
          }
          else
          {
          //do someting
          }
          有了異常以后,我們怎么做呢?
          try
          {
          aMethod();
          }catch(MyException e){
          //do someting
          }
          或者
          public anotherMethod() throws MyException
          {
          aMethod();
          }
          這里只列舉了一個最簡單的例子。如果aMethod()這個方法到處都需要調用,這種好處就會更顯著了。


          至于我們需要不需要使用異常呢?答案必然是肯定的。但是網上也有一些聲音說,異常是一種耗費性能的操作,應該少使或者盡量不使。我認為,這跟沒有很好的理解如何使用異常有關系。


          下面我就來說說,最重要的一點,也就是how,如何使用異常。


          首先,我們來看看,當發生異常的時候,JVM做了什么?



          為了拋出異常,JVM 發出 athrow 字節碼指令。 athrow 指令引起 JVM 將異常對象彈出執行堆棧。然后 JVM 搜索當前執行堆棧幀來尋找第一個 catch 子句,這個子句可以處理該類的一個異常或者其超類的一個異常。如果在當前的堆棧幀里沒有找到 catch block ,那么當前堆棧幀就被釋放,異常在下一個堆棧幀的上下文中被重新拋出,如此這般,直到找到包含匹配的 catch 子句的堆棧幀,或者是到了執行堆棧的底部。最后,如果沒找到適當的 catch 塊,所有的堆棧幀都會被釋放,線程在 ThreadGroup 對象有了處理異常的機會后被終止(參考 ThreadGroup.uncaughtException )。如果找到了適當的 catch 塊,程序計數器會重置到那一

          塊代碼的第一行。 (注:1)



          從上面的描述可以看出,拋出異常是一種代價很高的操作。有的人可能要問了,如果只是為了簡潔的代碼或者OO,這種代價值得嗎?我的回答是,不值得!!!這點和我上面說的并不沖突。如果有一點經濟學的知識,一定會知道邊際量這個概念,說白了就是我多花一個單位的成本,是否可以帶過我多于一單位的收益。將這點用到編程上也是通用的。
          我們可以考慮這樣一段代碼
          for(int i=0;i<list.size();i++)
          {
          AClass myClass = list.get(i);
          if(myClass.aValue!=null && !"".equals(myClass.aValue))
          {
          //do something
          }
          }


          這段代碼很好的處理了參數不正常的情況。但有一個問題,每次循環程序都需要判斷參數是否正常。假設我們知道大部分的參數都是正常的,那么這些操作就顯得有些浪費了。如果改成
          for(int i=0;i<list.size();i++)
          {
          AClass myClass = list.get(i);
          try
          {
          //do something
          }catch(Exception e){}
          }
          這樣只有當很小幾率發生錯誤的時候,我們就可以節省一些操作。這也就是經濟學上說的邊際收益大于邊際成本的時候,只有這個狀態,我們才應該這樣使。反觀另外一個狀態,如果我們不能確定參數是否大部分為正常或者我們確定大部分參數都不會為正常,那么就應該使用第一種方法。總之,這點是需要靈活掌握的。


          另外一個值得注意的地方就是,不要將異常用于流程跳轉,異常就是指異常的狀態,而不是控制語句。如果你能注意這點,你就已經避免了90%的錯誤異常應用。舉個例子。inputStream#read大家一定都用過,為什么read方法要返回-1作為讀取到文件尾的狀態,而不是用異常,就是這個道理。



          關于如何使用異常的另外一點就是,我們如何catch異常。這一點其實也很簡單,總結為一句話就是,如果你不知道如何處理這個異常,那么就不要catch這個異常。


          我們經常會遇見這樣一種情景:我們調用了某個接口,這個接口拋出了一個checkedexception。這個時候就是考驗你的時候了,catch還是throw 這是個問題。我的經驗是,如果你覺得這個異常是一個可恢復的異常,比如參數錯誤,那么你就需要catch這個

          exception,然后告訴用戶重新輸入。如果這個exception是一個不可恢復的exception,比如SQLException,那么你干脆就不要處理它,把它留給底層去處理,讓底層定向到統一的異常頁面。當然,這種操作并不是嚴格的,你也可以catch這個exception,然后返回到你自己的異常頁面。


          最值得注意的是,永遠不要沒有理由的私吞exception。比如
          try
          {



          }catch(Exception e){
          //do nothing
          }
          如果你確定可以這種做,那么沒有關系。但是如果你不能,千萬一定不要這么做,如果你這么做了,很有可能導致無法定位異常,把自己或者別人搞到死。



          關于如何使用異常的最后一個問題就是runtimeexception 或者 checkedexception,這是個問題!


          很長一段時間,我也曾困惑于這個問題,記得以前看過一本書,好像是java夜未眠,記不清楚了。里面說,要盡量使用runtimexception,但是當我這樣做的時候,問題就來了,調用我接口的人不知道我的方法會拋出什么異常,也就無從處理了,這樣就導致了程序的不健壯。其實這個問題需要根據你的業務進行判斷,沒有什么盡量或者最好。一個簡單的原則是如果希望客戶程序員有意識地采取措施,那么拋出checkedexception.舉兩個例子
          public void aMethod(String s)
          {
          if(s==null) throw new Runtimeexception();
          }
          public void otherMethod(String uri) throws NoSuchFileException
          {
          try
          {
          File file = new File(uri)
          }catch(IOException e)
          {
          throw new NoSuchFileException()
          }
          }


          看出點什么了嗎?你肯定很奇怪為什么都是參數不正確,第一個方法拋出的是一個RuntimeException而第二個是一個CheckedException。因為s為null是一個我們非期待的參數,而這種狀態可能并不是經常出現的,屬于一種非業務錯誤或者不可恢復異常,我們不需要明確的通知客戶程序員。



          而第二個不同,第二個異常代表用戶輸入了某種錯誤的參數,而這個異常需要客戶程序員去通知用戶。所以要求客戶程序員去catch這樣exception。


          以上是我對異常的一些理解,如果大家有不同意見可以進行討論


          參考資料
          1.關注性能: 異常的異常:http://www-128.ibm.com/developerworks/cn/java/j-perf02104/index.html
          2.異常設計----何使用異常的原則 http://www.cnblogs.com/javaVillage/articles/384483.html

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


          網站導航:
          博客園   IT新聞   Chat2DB   C++博客   博問  
           
          主站蜘蛛池模板: 黄平县| 宁乡县| 霍城县| 西乡县| 潜江市| 九台市| 麻江县| 五原县| 湘阴县| 台中市| 托里县| 保定市| 太谷县| 通河县| 中牟县| 渑池县| 宾阳县| 平潭县| 项城市| 东阳市| 邵东县| 自治县| 榕江县| 莒南县| 新乡县| 繁昌县| 土默特右旗| 高邮市| 江城| 都昌县| 连南| 崇仁县| 二手房| 禹城市| 通江县| 忻州市| 周宁县| 德化县| 大田县| 济宁市| 桂平市|