1. Arrays.asList
業務開發當中,我們常常會將原始的數組轉換為List類數據結構,來繼續展開各種Stream操作
- Arrays.asList無法轉換基本類型的數組,可以使用Arrays.stream來進行轉換
- Arrays.asList返回的list是不支持增刪操作的,其返回的List是Arrays的內部類ArrayList。內部繼承自AbstractList,沒有覆寫父類的add方法
- 對原始數組的修改會影響到我們獲得的那個List
- ArrayList實際上是使用了原始的數組,因此在使用的時候,最好再使用New ArrayList來實現解耦
2. 空值處理
2.1 NullPointerException
-
可能出現的場景
- 參數值是Integer等包裝類型,使用時因為自動拆箱出現了空指針異常
- 字符串比較
- ConcurrentHashMap這種容器不支持Key和Value為null,強行put null的key或Value會出現空指針異常
- 方法或遠程服務返回的list是null,沒做判空就直接調用,出現空指針異常
- 聯級調用的null check
-
best practice
string.equalsTo(variableName)
Optional.ofNullable()
orElse()
3. 異常處理
3.1 在業務代碼層面考慮異常處理
- 大多數業務應用都采用三層架構
- Controller層
- 負責信息收集,參數校驗,轉換服務層處理的數據適配前端,輕業務邏輯
- Controller 捕獲異常,然后需要給用戶友好用戶的提示
- Service層
- 負責核心業務邏輯,包括外部服務調用,訪問數據庫,緩存處理,消息處理等
- 一般會涉及到數據庫事務,出現異常不適合捕獲,否則事務無法自動回滾
- Repository層
- 負責數據訪問實現,一般沒有業務邏輯
- 根據情況來做忽略,降級,或者轉化為一個友好的異常
- Controller層
- 框架層面的異常處理
- 盡量不要在框架層面做異常的自動,統一的處理
- 框架應當來做兜底工作,如果異常上升到最上層邏輯還是無法處理的話,可以用統一的方式進行異常轉換
@RestControllerAdvice
@ExceptionHandler
3.2 不要直接生吞異常
捕獲了異常以后不應該生吞,因為吞掉的異常如果沒有正常處理的話,出現Bug會很難發現。
需要有合適的轉化成用戶友好的異常,或者至少在warn, error級別來做log
3.3 保留原始的信息
在捕捉了異常之后,一定要記得在log 或者在向外扔出的異常之中記錄原始異常信息
catch (IOException e) {
//只保留了異常消息,棧沒有記錄
log.error("文件讀取錯誤, {}", e.getMessage());
throw new RuntimeException("系統忙請稍后再試");
}
catch (IOException e) {
throw new RuntimeException("系統忙請稍后再試", e);
}123456789
另外,關注公眾號Java技術棧,在后台回復:面試,可以獲取我整理的 Java 系列面試題和答案,非常齊全。
3.4 小心finally中的異常 + try with resources
注意在資源釋放處理等收尾操作的時候也可能會出現異常,這種時候,如果try block邏輯和finnally邏輯都有異常拋出的話,try當中的異常會被finnally中的異常覆蓋掉,這會讓問題變得非常不明顯。
@GetMapping("wrong")
public void wrong() {
try {
log.info("try");
//異常丟失
throw new RuntimeException("try");
} finally {
log.info("finally");
throw new RuntimeException("finally");
}
}12345678910
對於實現了AutoCloseable接口的資源,可以使用try-with-resources來釋放資源,就是在try中帶資源的聲明
try catch finally vs try with resources
Scanner scanner = null;
try {
scanner = new Scanner(new File("test.txt"));
while (scanner.hasNext()) {
System.out.println(scanner.nextLine());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (scanner != null) {
scanner.close();
}
}
try (Scanner scanner = new Scanner(new File("test.txt"))) {
while (scanner.hasNext()) {
System.out.println(scanner.nextLine());
}
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
}
123456789101112131415161718192021
3.5 線程池任務的異常處理
設置自定義的異常處理程序作為保底,比如在聲明線程池時自定義線程池的未捕獲異常處理程序:
new ThreadFactoryBuilder()
.setNameFormat(prefix+"%d")
.setUncaughtExceptionHandler((thread, throwable)-> log.error("ThreadPool {} got exception", thread, throwable))
.get()1234
最后,關注公眾號Java技術棧,在后台回復:面試,可以獲取我整理的 Java 系列面試題和答案,非常齊全。
Reference
近期熱文推薦:
1.600+ 道 Java面試題及答案整理(2021最新版)
2.終於靠開源項目弄到 IntelliJ IDEA 激活碼了,真香!
3.阿里 Mock 工具正式開源,干掉市面上所有 Mock 工具!
4.Spring Cloud 2020.0.0 正式發布,全新顛覆性版本!
覺得不錯,別忘了隨手點贊+轉發哦!