Java 基礎常見知識點&面試題總結(下),2022 最新版!

2022-06-21 18:00:14

你好,我是 Guide。秋招即將到來,我對 JavaGuide 的內容進行了重構完善,同步一下最新更新,希望能夠幫助你。

前兩篇:

異常

Java 異常類層次結構圖概覽

Exception 和 Error 有什麼區別?

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

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

Checked Exception 和 Unchecked Exception 有什麼區別?

Checked Exception 即 受檢查異常 ,Java 程式碼在編譯過程中,如果受檢查異常沒有被 catch或者throws 關鍵字處理的話,就沒辦法通過編譯。

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

除了RuntimeException及其子類以外,其他的Exception類及其子類都屬於受檢查異常 。常見的受檢查異常有: IO 相關的異常、ClassNotFoundExceptionSQLException...。

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 返回值。

jvm 官方檔案中有明確提到:

If the try clause executes a return, the compiled code does the following:

  1. Saves the return value (if any) in a local variable.
  2. Executes a jsr to the code for the finally clause.
  3. Upon return from the finally clause, returns the value saved in the local variable.

程式碼範例:

public static void main(String[] args) {
    System.out.println(f(2));
}

public static int f(int value) {
    try {
        return value * value;
    } finally {
        if (value == 2) {
            return 0;
        }
    }
}

輸出:

0

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

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

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

try {
    System.out.println("Try to do something");
    throw new RuntimeException("RuntimeException");
} catch (Exception e) {
    System.out.println("Catch Exception -> " + e.getMessage());
    // 終止當前正在執行的Java虛擬機器器
    System.exit(1);
} finally {
    System.out.println("Finally");
}

輸出:

Try to do something
Catch Exception -> RuntimeException

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

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

相關 issue: https://github.com/Snailclimb/JavaGuide/issues/190