Java基礎常見面試題-異常-泛型
1 Exception 和 Error 有什麼差別?
1**
Exception
** :程式本身可以處理的異常,可以通過
catch
來進行捕獲。
Exception
又可以分為 Checked Exception (受檢查異常,必須處理) 和 Unchecked Exception (不受檢查異常,可以不處理)。
2**
Error
** :
Error
屬于程式無法處理的錯誤 。例如 Java 虛拟機運作錯誤(
Virtual MachineError
)、虛拟機記憶體不夠錯誤(
OutOfMemoryError
)、類定義錯誤(
NoClassDefFoundError
)等 。這些異常發生時,Java 虛拟機(JVM)一般會選擇線程終止。
2 Checked Exception 和 Unchecked Exception 有什麼差別?
Checked Exception 即 受檢查異常 ,Java 代碼在編譯過程中,如果受檢查異常沒有被
catch
或者
throws
關鍵字處理的話,就沒辦法通過編譯。
Unchecked Exception 即 不受檢查異常 ,Java 代碼在編譯過程中 ,我們即使不處理不受檢查異常也可以正常通過編譯。
3Throwable 類常用方法有哪些?
1
String getMessage()
: 傳回異常發生時的簡要描述
2
String toString()
: 傳回異常發生時的詳細資訊
3
String getLocalizedMessage()
: 傳回異常對象的本地化資訊。使用
Throwable
的子類覆寫這個方法,可以生成本地化資訊。如果子類沒有覆寫該方法,則該方法傳回的資訊與
getMessage()
傳回的結果相同
4
void printStackTrace()
: 在控制台上列印
Throwable
對象封裝的異常資訊
4 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
5 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
塊的代碼也不會被執行:
- 程式所在的線程死亡。
- 關閉 CPU。
6 異常使用有哪些需要注意的地方?
1 不要把異常定義為靜态變量,因為這樣會導緻異常棧資訊錯亂。每次手動抛出異常,我們都需要手動 new 一個異常對象抛出。
2 抛出的異常資訊一定要有意義。
3 建議抛出更加具體的異常比如字元串轉換為數字格式錯誤的時候應該抛出
NumberFormatException
而不是其父類
IllegalArgumentException
。
4 使用日志列印異常之後就不要再抛出異常了
二 、泛型
1 什麼是泛型?有什麼作用?
Java泛型是JDK5中引入的一個新特性。使用泛型參數可以增強代碼的可讀性以及穩定性。
泛型就是參數化類型或類型參數化
2 泛型的使用方式有哪幾種?
泛型一般有三種使用方式:泛型類、泛型接口、泛型方法。
1.泛型類:
//此處T可以随便寫為任意辨別,常見的如T、E、K、V等形式的參數常用于表示泛型
//在執行個體化泛型類時,必須指定T的具體類型
public class Generic<T>{
private T key;
public Generic(T key) {
this.key = key;
}
public T getKey(){
return key;
}
}
執行個體化泛型類:
Generic<Integer> genericInteger = new Generic<Integer>(123456);
2.泛型接口 :
public interface Generator<T> {
public T method();
}
3.泛型方法 :
public static < E > void printArray( E[] inputArray )
{
for ( E element : inputArray ){
System.out.printf( "%s ", element );
}
System.out.println();
}
3 項目中哪裡用到了泛型?
1 自定義接口通用傳回結果
CommonResult<T>
通過參數
T
可根據具體的傳回類型動态指定結果的資料類型
2 定義
Excel
處理類
ExcelUtil<T>
用于動态指定
Excel
導出的資料類型
3 建構集合工具類(參考
Collections
中的
sort
,
binarySearch
方法)。
三、反射
1 什麼是反射?
反射是指能通路、檢測、修改其本身狀态的能力;
2 反射的優缺點?
1 可以讓代碼編寫更加靈活,為各種架構提供開箱即用的功能便利。
2 反射讓我們在運作時有了分析操作類的能力的同時,但增加了安全問題。
3 反射性能較差(影響不大)
3 反射的應用場景有哪些?
Spring/Spring Boot、MyBatis 等等架構中都大量使用了反射機制。
四、注解
1 what is 注解?
Annotation
(注解) 是 Java5 開始引入的新特性,可以看作是一種特殊的注釋,主要用于修飾類、方法或者變量,提供某些資訊供程式在編譯或者運作時使用。
2 注解的解析方法有哪幾種?
編譯期直接掃描 :編譯器在編譯 Java 代碼的時候掃描對應的注解并處理。
運作期通過反射處理 :像架構中自帶的注解(比如 Spring 架構的
@Value
、
@Component
)都是通過反射來進行處理的。
五、SPI
1 什麼是SPI
SPI=Service Provider Interface,字面意思服務提供者的接口
2 SPI 和 API 有什麼差別?
API:實作方提供實作和接口,調用方進行調用。
SPI:接口存在于調用方,調用方确定接口規則,實作方根據規則進行實作。
3 SPI 的優缺點?
1 需要周遊加載所有的實作類,性能低;
2 當多個ServiceLoader 同時 load 時,會出現并發問題;
六、序列化和反序列化
1 什麼是序列化和反序列化?
序列化:就是将資料結構或者對象轉化為二進制位元組流的過程。
反序列化:将在序列化中産生的二進制位元組流轉換成資料結構或者對象。
序列化和反序列化常見應用場景:
- 對象在進行網絡傳輸;
- 将對象儲存到檔案前需要進行序列化,将對象從檔案中讀取出來需要進行反序列化。
- 對象存儲到資料庫需要序列化,資料庫讀出對象需要反序列化。
-
對象到記憶體-序列化,記憶體讀出對象-反序列化。
總結:序列化的目的就是在網絡傳輸對象或者将對象存儲到檔案系統、資料庫、記憶體中。
2 序列化協定對應于 TCP/IP 四層模型的哪一層?
- 應用層
- 傳輸層
- 網絡層
- 網絡接口層
3 如果有些字段不想進行序列化怎麼辦?
使用
transient
關鍵字修飾阻止序列化
transient
幾點注意:
1
transient
隻能修飾變量,不能修飾類和方法。
2
transient
修飾的變量,在反序列化後變量值将會被置成類型的預設值。例如,如果是修飾
int
類型,那麼反序列後結果就是
。
3
static
變量因為不屬于任何對象(Object),是以無論有沒有
transient
關鍵字修飾,均不會被序列化。
比較常用的序列化協定有 Hessian、Kryo、Protobuf、ProtoStuff,這些都是基于二進制的序列化協定。
4 為什麼不推薦使用 JDK 自帶的序列化?
- 不支援跨語言調用;
- 性能差;
- 存在安全問題;
七、I/O
1 Java I/O流是什麼?
IO 即
Input/Output
,輸入和輸出。資料輸入到計算機記憶體的過程即輸入,反之輸出到外部存儲(比如資料庫,檔案,遠端主機)的過程即輸出。
-
/InputStream
: 所有的輸入流的基類,前者是位元組輸入流,後者是字元輸入流。Reader
-
/OutputStream
: 所有輸出流的基類,前者是位元組輸出流,後者是字元輸出流。Writer
2 I/O 流為什麼要分為位元組流和字元流呢?
- 字元流是由 Java 虛拟機将位元組轉換得到的,這個過程還算是比較耗時;
- 如果我們不知道編碼類型的話,使用位元組流的過程中很容易出現亂碼問題。
3 什麼是文法糖?
文法糖(Syntactic sugar) 代指的是程式設計語言為了友善程式員開發程式而設計的一種特殊文法,這種文法對程式設計語言的功能并沒有影響
Java 中最常用的文法糖主要有泛型、自動拆裝箱、變長參數、枚舉、内部類、增強 for 循環、try-with-resources 文法、lambda 表達式等。