1. 程式人生 > 其它 >效能問題之CPU消耗高

效能問題之CPU消耗高

Java 異常類層次結構圖概覽 :

Exception 和 Error 有什麼區別?

在 Java 中,所有的異常都有一個共同的祖先 java.lang 包中的 Throwable 類。Throwable 類有兩個重要的子類:

Exception :程式本身可以處理的異常,可以通過 catch 來進行捕獲。Exception 又可以分為 Checked Exception (受檢查異常,必須處理) 和 Unchecked Exception (不受檢查異常,可以不處理)。
Error :Error 屬於程式無法處理的錯誤 ,我們沒辦法通過 catch 來進行捕獲不建議通過catch捕獲 。例如 Java 虛擬機器執行錯誤(Virtual MachineError)、虛擬機器記憶體不夠錯誤(OutOfMemoryError)、類定義錯誤(NoClassDefFoundError)等 。這些異常發生時,Java 虛擬機器(JVM)一般會選擇執行緒終止。

Checked Exception 和 Unchecked Exception 有什麼區別?

hecked Exception 即 受檢查異常 ,Java 程式碼在編譯過程中,如果受檢查異常沒有被 catch/throw 處理的話,就沒辦法通過編譯 。

比如下面這段 IO 操作的程式碼

除了RuntimeException及其子類以外,其他的Exception類及其子類都屬於受檢查異常 。常見的受檢查異常有: IO 相關的異常、ClassNotFoundException 、SQLException...。
Unchecked Exception 即 不受檢查異常 ,Java 程式碼在編譯過程中 ,我們即使不處理不受檢查異常也可以正常通過編譯。

RuntimeException 及其子類都統稱為非受檢查異常,常見的有(建議記下來,日常開發中會經常用到):
NullPointerException(空指標錯誤)
IllegalArgumentException(引數錯誤比如方法入參型別錯誤)
NumberFormatException(字串轉換為數字格式錯誤,IllegalArgumentException的子類)
ArrayIndexOutOfBoundsException(陣列越界錯誤)
ClassCastException(型別轉換錯誤)
ArithmeticException(算術錯誤)
SecurityException (安全錯誤比如許可權不夠)
UnsupportedOperationException(不支援的操作錯誤比如重複建立同一使用者)

Throwable 類常用方法有哪些?

String getMessage(): 返回異常發生時的簡要描述
String toString(): 返回異常發生時的詳細資訊
String getLocalizedMessage(): 返回異常物件的本地化資訊。使用 Throwable 的子類覆蓋這個方法,可以生成本地化資訊。如果子類沒有覆蓋該方法,則該方法返回的資訊與 getMessage()返回的結果相同
void printStackTrace(): 在控制檯上列印 Throwable 物件封裝的異常資訊

try-catch-finally 如何使用?
try塊 : 用於捕獲異常。其後可接零個或多個 catch 塊,如果沒有 catch 塊,則必須跟一個 finally 塊。
*catch塊 : 用於處理 try 捕獲到的異常。
finally 塊 : 無論是否捕獲或處理異常,finally 塊裡的語句都會被執行。當在 try 塊或 catch 塊中遇到 return 語句時,finally 語句塊將在方法返回之前被執行。

try {
    System.out.println("Try to do something");
    throw new RuntimeException("RuntimeException");
} catch (Exception e) {
    System.out.println("Catch Exception -> " + e.getMessage());
} finally {
    System.out.println("Finally");
}

輸出:

Try to do something
Catch Exception -> RuntimeException
Finally

注意:不要在 finally 語句塊中使用 return! 當 try 語句和 finally 語句中都有 return 語句時,try 語句塊中的 return 語句會被忽略。這是因為 try 語句中的 return 返回值會先被暫存在一個本地變數中,當執行到 finally 語句中的 return 之後,這個本地變數的值就變為了 finally 語句中的 return 返回值。

finally 中的程式碼一定會執行嗎?

不一定的!在某些情況下,finally 中的程式碼不會被執行。

就比如說 finally 之前虛擬機器被終止執行的話,finally 中的程式碼就不會被執行

另外,在以下 2 種特殊情況下,finally 塊的程式碼也不會被執行:

1 程式所在的執行緒死亡。
2 關閉 CPU。

如何使用 try-with-resources 代替try-catch-finally

ava 中類似於InputStream、OutputStream 、Scanner 、PrintWriter等的資源都需要我們呼叫close()方法來手動關閉,一般情況下我們都是通過try-catch-finally語句來實現這個需求,如下

//讀取文字檔案的內容
Scanner scanner = null;
try {
    scanner = new Scanner(new File("D://read.txt"));
    while (scanner.hasNext()) {
        System.out.println(scanner.nextLine());
    }
} catch (FileNotFoundException e) {
    e.printStackTrace();
} finally {
    if (scanner != null) {
        scanner.close();
    }
}

使用 Java 7 之後的 try-with-resources 語句改造上面的程式碼:

try (Scanner scanner = new Scanner(new File("test.txt"))) {
    while (scanner.hasNext()) {
        System.out.println(scanner.nextLine());
    }
} catch (FileNotFoundException fnfe) {
    fnfe.printStackTrace();
}
###異常使用有哪些需要注意的地方?
不要把異常定義為靜態變數,因為這樣會導致異常棧資訊錯亂。每次手動丟擲異常,我們都需要手動 new 一個異常物件丟擲。
丟擲的異常資訊一定要有意義。
建議丟擲更加具體的異常比如字串轉換為數字格式錯誤的時候應該丟擲NumberFormatException而不是其父類IllegalArgumentException。
使用日誌列印異常之後就不要再丟擲異常了(兩者不要同時存在一段程式碼邏輯中)。```