@SneakyThrows

@SneakyThrows

大膽拋出已檢查的異常,以前沒有人拋出它們!

Overview

@SneakyThrows可以用來偷偷拋出已檢查的異常而不在方法的throws子句中實際聲明這一點。當然,應該謹慎使用這種有爭議的能力。由lombok生成的代碼不會忽略,包裝,替換或以其他方式修改拋出的已檢查異常; 它只是僞造了編譯器。在JVM(類文件)級別,無論方法的throws子句如何,都可以拋出所有異常,無論是否檢查,這就是爲什麼這樣做的原因。

當您想要選擇退出已檢查的異常機制時,常見的用例圍繞兩種情況:
一個不必要的嚴格的接口,例如Runnable- 無論是否傳播出你的run()方法,檢查與否,它都將被傳遞給Thread未處理的異常處理程序。捕獲已檢查的異常並將其包裝在某種情況RuntimeException下只會模糊問題的真正原因。
一個'不可能'的例外。例如,new String(someByteArray, "UTF-8");聲明它可以拋出UnsupportedEncodingException但是根據JVM規範,UTF-8 必須始終可用。一個UnsupportedEncodingException在這裏大約是有可能的ClassNotFoundError,當你使用一個String對象,而你沒有趕上那些要麼!
請注意,直接捕獲偷偷摸摸的已檢查類型是不可能的,因爲javac不允許您爲try體中沒有方法調用聲明爲拋出的異常類型編寫catch塊。此問題與上面列出的任何一個用例都無關,所以請注意這個問題,不要在@SneakyThrows沒有經過深思熟慮的情況下使用該機制!

您可以將任意數量的例外傳遞給@SneakyThrows註釋。如果你沒有通過任何例外,你可以偷偷地拋出任何例外。

With Lombok

import lombok.SneakyThrows;

public class SneakyThrowsExample implements Runnable {
  @SneakyThrows(UnsupportedEncodingException.class)
  public String utf8ToString(byte[] bytes) {
    return new String(bytes, "UTF-8");
  }
  
  @SneakyThrows
  public void run() {
    throw new Throwable();
  }
}

Vanilla Java

import lombok.Lombok;

public class SneakyThrowsExample implements Runnable {
  public String utf8ToString(byte[] bytes) {
    try {
      return new String(bytes, "UTF-8");
    } catch (UnsupportedEncodingException e) {
      throw Lombok.sneakyThrow(e);
    }
  }
  
  public void run() {
    try {
      throw new Throwable();
    } catch (Throwable t) {
      throw Lombok.sneakyThrow(t);
    }
  }
}

Supported configuration keys:

lombok.sneakyThrows.flagUsage = [warning | error] (default: not set)

Small print

因爲@SneakyThrows是一個實現細節而不是方法簽名的一部分,所以當你不調用任何拋出此異常的方法時,如果你試圖將一個被檢查的異常聲明爲偷偷拋出則是一個錯誤。(throws對於容納子類的語句,這樣做是完全合法的)。同樣,@SneakyThrows不繼承。

對於人羣中的不同說法者:開箱即用,Eclipse將爲未捕獲的異常提供“快速修復”,這些異常包含在catch塊中的try / catch塊中的違規語句e.printStackTrace()。與僅僅偷偷地拋出異常相比,這是非常無效的,Roel和Reinier認爲被檢查的異常系統遠非完美,因此有理由選擇退出機制。

如果你加上@SneakyThrows一個構造函數,那麼對兄弟或超級構造函數的任何調用都將被排除在@SneakyThrows處理之外。這是我們無法解決的java限制:對兄弟/超級構造函數的調用必須是構造函數中的第一個語句; 它們不能放在try / catch塊中。

@SneakyThrows 在一個空方法,或一個空的構造函數或只有一個兄弟/超級構造函數的調用導致沒有try / catch塊和警告
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章