Java:如何正确地使用异常详解
概述:
? Java中的異常機制是一個好東西。不過好東西也要正確地使用才行,不然就會讓我們錯誤地認識它。在錯誤地認識狀況下,就會錯誤地使用。這樣就成了一個惡性地循環了。這不是我們愿意看到的。不要以為我們已經可以很好地使用異常了,下面就針對部分問題作一個講解。這部分的問題中,有一些是來自《Effective Java》這本書中,有一部分是來自本人平時開發過程中遇到的。
本文鏈接:http://blog.csdn.net/lemon_tree12138/article/details/50474230 -- Coding-Naga
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?--轉載請注明出處
1.是throw還是try-catch
? 這個是一個對剛接觸編程開發的人來說,經常面臨但又選擇不好的問題。
? 由于我們開發的項目可不是像寫Demo一樣輕松,這里可能會有很多層次結構。我們要在具體哪一層的什么位置是使用try-catch這個異常呢,還是把異常throw到上一層呢?這里,我們首先要知道一件事,那就是try-catch和throw分別會發生什么情況呢?
try-catch: 捕獲一個異常情況,并中止try塊中的后續操作。且不會再向上拋出異常了。
throw: 當使用throw拋出一個異常時,當前的執行塊(方法)會結束后續的執行。相當于一個return操作,并保證了上層在調用的時候可以捕獲到這個異常,并做相應處理。
Demo示例如下:
public class ExceptionClient {public static void main(String[] args) {ExceptionClient client = new ExceptionClient();client.showInfo();}private void showInfo() {try {System.out.println("first info");testException();System.out.println("second info");} catch (Exception e) {System.err.println(e);}System.out.println("outside info");}private void testException() throws AException {boolean f = true;if (f) {throw new AException("AException");}System.out.println("f is false.");} } ? 按照上面對try-catch和throw的分析,可以知道,showInfo方法try塊中的第二句話是不打印的,而testException方法的最后一句也是不打印的。結果如下:
圖-1 try-catch測試結果
2.是使用受檢的異常還是非受檢的異常
? 首先我們要了解什么是受檢異常和非受檢異常,不過這里顧名思義,受檢即接受檢查。由于目前的IDE很是智能,當我們在使用受檢異常而未try-catch這個異常時,IDE會給出錯誤提示。如下:
圖-2 IDE對受檢異常的檢查
? 而非受檢異常則不會被IDE識別。還有一點,因為前面說到IDE會檢測到受檢異常,所以,這里如果我們強行運行此代碼,是通不過編譯的,非受檢異常則不會。
? 好了,說明了受檢異常和非受檢異常在使用過程中的區別。現在就來說說怎么創建這些不同的異常吧。
? 當我們要編寫自定義的受檢異常A.java時,A的class需要繼承Exception,而非受檢異常B.java則是繼承RuntimeException。
? 由于受檢異常會在使用的過程,強行限制開發人員去try-catch。而在try-catch此異常的時候,開發人員則可以對此異常進行修正并重新之前的操作(即恢復)。在RuntimeException中則沒有這樣的限制。所以,當我們試圖告訴調用者,當前的異常是可以被修復,并允許重新去調用的時候,我們就使用受檢的異常,當我們認為這是一個程序錯誤的時候,則需要使用非受檢異常。
? 可能對在何時使用受檢異?;蚍鞘軝z異常有了一些基本認識,然后你可能會問這樣的一個問題:我們不是還有一個Error么,那么錯誤(Error)和異常有什么區別呢?下面就列舉了這兩者之間的區別(點擊查看參考來源):
Exception:
1.可以是可被控制(checked) 或不可控制的(unchecked)。
2.表示一個由程序員導致的錯誤。
3.應該在應用程序級被處理。
Error:
1.總是不可控制的(unchecked)。
2.經常用來用于表示系統錯誤或低層資源的錯誤。
3.如何可能的話,應該在系統級被捕捉。
3.只針對不正確的條件才使用異常
? 關于這一點,首先我們應該了解的是Java在進行異常檢查時消耗的系統資源,要比普通的程序調用高。那么,如果我們的程序在不停地進行異常檢查,就會對程序整個的性能產生不小的影響。我們可以從一個小例子中看出這一點。如下:
假設現有10000000個元素的List,我們要對此List進行遍歷,有三種方式,分別如下:
第一種:對每一種情況進行異常檢查
private void call_1(List<Integer> list) {long t = System.currentTimeMillis();try {int index = 0;while(true) {list.get(index++);} } catch (IndexOutOfBoundsException e) {LogUtils.printTimeUsed("不針對檢查異常", t);}}
第二種:只對錯誤的情況進行異常檢查
private void call_2(List<Integer> list) {long t = System.currentTimeMillis();t = System.currentTimeMillis();int size = list.size();int index = 0;while(true) {if (index >= size) {try {list.get(index++);} catch (IndexOutOfBoundsException e) {LogUtils.printTimeUsed("針對性檢查異常", t);break;}}list.get(index++);}}第三種:普通的循環遍歷
private void call_3(List<Integer> list) {long t = System.currentTimeMillis();t = System.currentTimeMillis();int size = list.size();int index = 0;for (index = 0; index < size; index++) {list.get(index++);}LogUtils.printTimeUsed("循環遍歷", t);}測試結果:
圖-3 不同異常檢查方式遍歷List
? 從上面的測試結果中,我們可以看到不針對地檢查異常(盲目地檢查異常),比有針對性地檢查異常性能上低了不少。所以,我們在使用異常的時候,請格外謹慎。需要去避免一些不必要的異常檢查,以優化我們的程序代碼。
Ref:
《Effective?Java》
總結
以上是生活随笔為你收集整理的Java:如何正确地使用异常详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 操作系统:基于页面置换算法的缓存原理详解
- 下一篇: JSunpack-n的安装与简单使用