偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

如何優(yōu)雅地處理程序異常,真的是一門學(xué)問

開發(fā) 前端
NullPointerException 并不是程序出現(xiàn)問題的本因,但實(shí)際上它出現(xiàn)了,無形當(dāng)中干擾了我們的視線。正確的做法是延遲捕獲異常,讓程序在第一個(gè)異常捕獲后就終止執(zhí)行。
  • 修復(fù)若干 bug
  • 殺了某程序員祭天,并成功解決掉他遺留的 bug

作為一名負(fù)責(zé)任的程序員,我們當(dāng)然希望程序不會(huì)出現(xiàn) bug,因?yàn)?bug 出現(xiàn)的越多,間接地證明了我們的編程能力越差,至少領(lǐng)導(dǎo)是這么看的。

事實(shí)上,領(lǐng)導(dǎo)是不會(huì)拿自己的腦袋宣言的:“我們的程序絕不存在任何一個(gè) bug?!钡?dāng)程序出現(xiàn) bug 的時(shí)候,領(lǐng)導(dǎo)會(huì)毫不猶豫地選擇讓程序員背鍋。

為了讓自己少背鍋,我們可以這樣做:

  • 在編碼階段合理使用異常處理機(jī)制,并記錄日志以備后續(xù)分析
  • 在測(cè)試階段進(jìn)行大量有效的測(cè)試,在用戶發(fā)現(xiàn)錯(cuò)誤之前發(fā)現(xiàn)錯(cuò)誤

還有一點(diǎn)需要做的是,在敲代碼之前,學(xué)習(xí)必要的編程常識(shí),做到兵馬未動(dòng),糧草先行。

Java 異常的層次圖

圖片圖片

Error 類異常描述了 Java 運(yùn)行時(shí)系統(tǒng)的內(nèi)部錯(cuò)誤,比如最常見的 OutOfMemoryError 和 NoClassDefFoundError。

導(dǎo)致 OutOfMemoryError 的常見原因有以下幾種:

  • 內(nèi)存中加載的數(shù)據(jù)量過于龐大,如一次從數(shù)據(jù)庫取出過多數(shù)據(jù);
  • 集合中的對(duì)象引用在使用完后未清空,使得 JVM 不能回收;
  • 代碼中存在死循環(huán)或循環(huán)產(chǎn)生過多重復(fù)的對(duì)象;
  • 啟動(dòng)參數(shù)中內(nèi)存的設(shè)定值過小;

OutOfMemoryError 的解決辦法需要視情況而定,但問題的根源在于程序的設(shè)計(jì)不夠合理,需要通過一些性能檢測(cè)才能找得出引發(fā)問題的根源。

導(dǎo)致 NoClassDefFoundError 的原因只有一個(gè),Java 虛擬機(jī)在編譯時(shí)能找到類,而在運(yùn)行時(shí)卻找不到。

圖片圖片

NoClassDefFoundError 的解決辦法,我截了一張圖,如上所示。當(dāng)一個(gè)項(xiàng)目引用了另外一個(gè)項(xiàng)目時(shí),切記這一步!

Exception(例外)通??煞譃閮深?,一類是寫代碼的人造成的,比如訪問空指針(NullPointerException)。應(yīng)當(dāng)在敲代碼的時(shí)候進(jìn)行檢查,以杜絕這類異常的發(fā)生。

if (str == null || "".eqauls(str)) {
}

另外一類異常不是寫代碼的人造成的,要么需要拋出,要么需要捕獲,比如說常見的 IOException。拋出的示例。

public static void main(String[] args) throws IOException {
    InputStream is = new FileInputStream("test.txt");
    int b;
    while ((b = is.read()) != -1) {

    }
}

捕獲的示例。

public static void main(String[] args) {
    try {
        InputStream is = new FileInputStream("test.txt");
        int b;
        while((b = is.read()) != -1) {

        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

當(dāng)拋出異常的時(shí)候,剩余的代碼就會(huì)終止執(zhí)行,這時(shí)候一些資源就需要主動(dòng)回收。

Java 的解決方案就是 finally 子句——不管異常有沒有被捕獲,finally 子句里的代碼都會(huì)執(zhí)行。

在下面的示例當(dāng)中,輸入流將會(huì)被關(guān)閉,以釋放資源。

public static void main(String[] args) {
    InputStream is = null;
    try {
        is = new FileInputStream("test.txt");
        int b;
        while ((b = is.read()) != -1) {}
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        is.close();
    }
}

但我總覺得這樣的設(shè)計(jì)有點(diǎn)問題,因?yàn)?nbsp;close() 方法同樣會(huì)拋出 IOException:

public void close() throws IOException {}

也就是說,調(diào)用 close() 的 main 方法要么需要拋出 IOException,要么需要在 finally 子句里重新捕獲 IOException。

選擇前一種就會(huì)讓 try catch 略顯尷尬,就像下面這樣。

public static void main(String[] args) throws IOException {
    InputStream is = null;
    try {
        is = new FileInputStream("test.txt");
        int b;
        while ((b = is.read()) != -1) {}
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        is.close();
    }
}

選擇后一種會(huì)讓代碼看起來很臃腫,就像下面這樣。

public static void main(String[] args) {
    InputStream is = null;
    try {
        is = new FileInputStream("test.txt");
        int b;
        while ((b = is.read()) != -1) {}
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

總之,我們需要另外一種更優(yōu)雅的解決方案。JDK7 新增了 Try-With-Resource 語法:如果一個(gè)類(比如 InputStream)實(shí)現(xiàn)了 AutoCloseable 接口,那么就可以將該類的對(duì)象創(chuàng)建在 try 關(guān)鍵字后面的括號(hào)中,當(dāng) try-catch 代碼塊執(zhí)行完畢后,Java 會(huì)確保該對(duì)象的 close方法被調(diào)用。示例如下。

public static void main(String[] args) {
    try (InputStream is = new FileInputStream("test.txt")) {
        int b;
        while ((b = is.read()) != -1) {
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

異常處理的一些心得

1)盡量捕獲原始的異常

實(shí)際應(yīng)該捕獲 FileNotFoundException,卻捕獲了泛化的 Exception。示例如下。

InputStream is = null;
try {
    is = new FileInputStream("test.txt");
} catch (Exception e) {
    e.printStackTrace();
}

這樣做的壞處顯而易見:假如你喊“王二”,那么我就敢答應(yīng);假如你喊“老王”,那么我還真不敢答應(yīng),萬一你喊的我妹妹“王三”呢?很多初學(xué)者誤以為捕獲泛化的 Exception 更省事,但也更容易讓人“丈二和尚摸不著頭腦”。相反,捕獲原始的異常能夠讓協(xié)作者更輕松地辨識(shí)異常類型,更容易找出問題的根源。

2)盡量不要打印堆棧后再拋出異常

當(dāng)異常發(fā)生時(shí)打印它,然后重新拋出它,以便調(diào)用者能夠適當(dāng)?shù)靥幚硭>拖裣旅孢@段代碼一樣。

public static void main(String[] args) throws IOException {
    try (InputStream is = new FileInputStream("test.txt")) {
    }catch (IOException e) {
        e.printStackTrace();
        throw e;
    } 
}

這似乎考慮得很周全,但是這樣做的壞處是調(diào)用者可能也打印了異常,重復(fù)的打印信息會(huì)增添排查問題的難度。

java.io.FileNotFoundException: test.txt (系統(tǒng)找不到指定的文件。)
    at java.io.FileInputStream.open0(Native Method)
    at java.io.FileInputStream.open(FileInputStream.java:195)
    at java.io.FileInputStream.<init>(FileInputStream.java:138)
    at java.io.FileInputStream.<init>(FileInputStream.java:93)
    at learning.Test.main(Test.java:10)
Exception in thread "main" java.io.FileNotFoundException: test.txt (系統(tǒng)找不到指定的文件。)
    at java.io.FileInputStream.open0(Native Method)
    at java.io.FileInputStream.open(FileInputStream.java:195)
    at java.io.FileInputStream.<init>(FileInputStream.java:138)
    at java.io.FileInputStream.<init>(FileInputStream.java:93)
    at learning.Test.main(Test.java:10)

3)千萬不要用異常處理機(jī)制代替判斷

我曾見過類似下面這樣奇葩的代碼,本來應(yīng)該判 null 的,結(jié)果使用了異常處理機(jī)制來代替。

public static void main(String[] args) {
    try {
        String str = null;
        String[] strs = str.split(",");
    } catch (NullPointerException e) {
        e.printStackTrace();
    }
}

捕獲異常相對(duì)判斷花費(fèi)的時(shí)間要多得多!我們可以模擬兩個(gè)代碼片段來對(duì)比一下。代碼片段 A:

long a = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
    try {
        String str = null;
        String[] strs = str.split(",");
    } catch (NullPointerException e) {
    }
}
long b = System.currentTimeMillis();
System.out.println(b - a);

代碼片段 B:

long a = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
    String str = null;
    if (str != null) {
        String[] strs = str.split(",");
    }
}
long b = System.currentTimeMillis();
System.out.println(b - a);

100000 萬次的循環(huán),代碼片段 A(異常處理機(jī)制)執(zhí)行的時(shí)間大概需要 1983 毫秒;代碼片段 B(正常判斷)執(zhí)行的時(shí)間大概只需要 1 毫秒。這樣的比較雖然不夠精確,但足以說明問題。

4)不要盲目地過早捕獲異常

如果盲目地過早捕獲異常的話,通常會(huì)導(dǎo)致更嚴(yán)重的錯(cuò)誤和其他異常。請(qǐng)看下面的例子。

InputStream is = null;
try {
    is = new FileInputStream("test.txt");

} catch (FileNotFoundException e) {
    e.printStackTrace();
}

int b;
try {
    while ((b = is.read()) != -1) {
    }
} catch (IOException e) {
    e.printStackTrace();
}

finally {
    try {
        is.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

假如文件沒有找到的話,InputStream 的對(duì)象引用 is 就為 null,新的 NullPointerException 就會(huì)出現(xiàn)。

java.io.FileNotFoundException: test.txt (系統(tǒng)找不到指定的文件。)
    at java.io.FileInputStream.open0(Native Method)
    at java.io.FileInputStream.open(FileInputStream.java:195)
    at java.io.FileInputStream.<init>(FileInputStream.java:138)
    at java.io.FileInputStream.<init>(FileInputStream.java:93)
    at learning.Test.main(Test.java:12)
Exception in thread "main" java.lang.NullPointerException
    at learning.Test.main(Test.java:28)

NullPointerException 并不是程序出現(xiàn)問題的本因,但實(shí)際上它出現(xiàn)了,無形當(dāng)中干擾了我們的視線。正確的做法是延遲捕獲異常,讓程序在第一個(gè)異常捕獲后就終止執(zhí)行。

好了,關(guān)于異常我們就說到這。

異常處理是程序開發(fā)中必不可少的操作之一,但如何正確優(yōu)雅地對(duì)異常進(jìn)行處理卻是一門學(xué)問,好的異常處理機(jī)制可以確保程序的健壯性,提高系統(tǒng)的可用率。

責(zé)任編輯:武曉燕 來源: Java極客技術(shù)
相關(guān)推薦

2024-09-26 10:51:51

2025-01-20 07:10:00

LambdaJavanull

2015-07-28 15:35:48

學(xué)習(xí)語言

2023-05-12 12:09:38

職責(zé)鏈模式客服

2014-07-22 09:01:53

SwiftJSON

2012-03-28 09:40:40

JavaScript

2020-09-27 15:52:02

編程語言C 語言Python

2024-01-15 08:09:44

Fluent錯(cuò)誤代碼

2022-02-27 14:45:16

編程語言JavaC#

2019-11-18 11:00:58

程序員編程語言

2022-11-04 11:11:15

語言入職項(xiàng)目

2020-11-12 07:00:50

JavaScript前端編程語言

2023-10-10 13:23:18

空指針異常Java

2015-05-15 09:53:51

RackspaceIT業(yè)務(wù)

2015-05-18 13:28:09

中小企業(yè)IT云服務(wù)

2022-02-21 11:15:59

編程語言后端開發(fā)

2024-06-27 09:00:00

人工智能編程語言軟件開發(fā)

2022-08-03 08:41:30

客戶端操作并發(fā)請(qǐng)求

2023-02-15 14:34:42

蘋果汽車新能源汽車

2011-05-24 15:47:08

網(wǎng)頁制作
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)