Lombok注解-@SneakyThrows的使用
Lombok注解@SneakyThrows
@SneakyThrows注解的用途得從java的異常設計體系說起。
java中我們常見的2類異常。
- 1.普通Exception類,也就是我們常說的受檢異常或者Checked Exception。
- 2.RuntimeException類,既運行時異常。
前者會強制要求拋出它的方法聲明throws,調(diào)用者必須顯示的去處理這個異常。設計的目的是為了提醒開發(fā)者處理一些場景中必然可能存在的異常情況。比如網(wǎng)絡異常造成IOException。
但是現(xiàn)實,往往事與愿違。大部分情況下的異常,我們都是一路往外拋了事。(強制處理我也處理不了啊!臣妾做不到)所以漸漸的java程序員處理Exception的常見手段就是外面包一層RuntimeException,接著往上丟。這種解決思想尤其在Spring中到處出現(xiàn)。
try { } catch (Exception e){ ? ?throw new RuntimeException(e); }
Lombok的@SneakyThrows就是為了消除這樣的模板代碼。
使用注解后不需要擔心Exception的處理
?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(); ? } }
真正生成的代碼
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); ? ? } ? } }
原理
顯然魔法 藏在Lombok.sneakyThrow(t);中??赡艽蠹叶紩詾檫@個方法就是new RuntimeException()之類的。然而事實并非如此。閱讀代碼可以看出整個方法其實最核心的邏輯是throw (T)t;,利用泛型將我們傳入的Throwable強轉(zhuǎn)為RuntimeException。雖然事實上我們不是RuntimeException。但是沒關(guān)系。因為JVM并不關(guān)心這個。泛型最后存儲為字節(jié)碼時并沒有泛型的信息。這樣寫只是為了騙過javac編譯器。源碼中注釋有解釋。
? ? public static RuntimeException sneakyThrow(Throwable t) { ? ? ? ? if (t == null) throw new NullPointerException("t"); ? ? ? ? return Lombok.<RuntimeException>sneakyThrow0(t); ? ? } ? ? private static <T extends Throwable> T sneakyThrow0(Throwable t) throws T { ? ? ? ? throw (T)t; ? ? }
lombok注解@SneakyThrows探索及與try catch、throws Exception區(qū)別
我在一個開源項目中看到了lombok注解@SneakyThrows,于是探索實踐了一下,有些事情還是要自己操作一下,不然還真的不知道?。?/p>
以前就看到項目里有@SneakyThrows注解,一直沒去管他和手動try catch還有往上拋異常有什么區(qū)別?
先說一下結(jié)論,趕時間的朋友看了就可以走了哈??!
我們發(fā)現(xiàn),@SneakyThrows注解在編譯的時候自動幫我們try catch,使用@SneakyThrows是為了讓代碼更加簡潔,加快我們的開發(fā)效率??!所以還是推薦使用@SneakyThrows來解決異常問題,當然如果是已知異常還是自己手動throw。
導入 Maven
<!--Lombok--> <dependency> ?? ?<groupId>org.projectlombok</groupId> ?? ?<artifactId>lombok</artifactId> ?? ?<scope>provided</scope> </dependency>
方法測試
public class SneakyTest { ? ? public static void main(String[] args) { ? ? ? ? exceptionTest(); ? ? } ? ? public static void exceptionTest(){ ? ? ? ? // 模擬一個異常 ? ? ? ? FileInputStream fis = new FileInputStream(new File("test.txt")); ? ? } }
此時Idea提醒我們要捕獲異常,不然無法通過編譯,給出我們?nèi)N解決方案,也就是我們本次要探究的目的??!
我們先第一種方式:
public class SneakyTest { public static void main(String[] args) throws FileNotFoundException { exceptionTest(); } public static void exceptionTest() throws FileNotFoundException { // 模擬一個異常 FileInputStream fis = new FileInputStream(new File("D:\\test.txt")); } }
我們看到我們往上級拋,上級也需要拋,這種一直拋還是要有人處理,所以我們不建議這樣!
第二種方式:
public class SneakyTest { public static void main(String[] args) { exceptionTest(); } public static void exceptionTest(){ // 模擬一個異常 try { FileInputStream fis = new FileInputStream(new File("D:\\test.txt")); } catch (FileNotFoundException e) { e.printStackTrace(); } } }
我們在本方法內(nèi)處理,這樣就不需要調(diào)用者處理了??!
第三種方式:
也是小編一直疑惑的,為啥會有這個注解,有什么優(yōu)點嗎??
先看解決方式,我們在編譯一下看看究竟怎么解決的異常??!
public class SneakyTest { public static void main(String[] args) { exceptionTest(); } @SneakyThrows public static void exceptionTest(){ // 模擬一個異常 FileInputStream fis = new FileInputStream(new File("D:\\test.txt"));; } }
我們編譯一下看一下,下面是class文件
public class SneakyTest { public SneakyTest() { } public static void main(String[] args) { exceptionTest(); } public static void exceptionTest() { try { new FileInputStream(new File("D:\\test.txt")); } catch (Throwable var1) { throw var1; } } }
我們發(fā)現(xiàn),這個注解自動幫我們try catch,使用@SneakyThrows是為了讓代碼更加簡潔,加快我們的開發(fā)效率??!
這樣我們就測試完成了,主要介紹了@SneakyThrows到底幫我們解決了什么問題,我們?yōu)槭裁匆褂聾SneakyThrows。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
淺析Java迭代器Iterator和Iterable的區(qū)別
Java語言中,Iterator和Iterable都是用來遍歷集合類數(shù)據(jù)結(jié)構(gòu)的接口,雖然它們有很多相似的地方,但在具體實現(xiàn)中卻有著一些不同之處,本文將詳細分析它們的區(qū)別,并提供相應的代碼示例,需要的朋友可以參考下2023-07-07ThreadPoolExecutor參數(shù)含義及源碼執(zhí)行流程詳解
這篇文章主要為大家介紹了ThreadPoolExecutor參數(shù)含義及源碼執(zhí)行流程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-11-11Spring boot監(jiān)控Actuator-Admin實現(xiàn)過程詳解
這篇文章主要介紹了Spring boot監(jiān)控Actuator-Admin實現(xiàn)過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-09-09Java EasyExcel實現(xiàn)導出多sheet并設置單元格樣式
EasyExcel是一個基于Java的、快速、簡潔、解決大文件內(nèi)存溢出的Excel處理工具,下面我們就來學習一下EasyExcel如何實現(xiàn)導出多sheet并設置單元格樣式吧2023-11-11Spring?boot?Jpa添加對象字段使用數(shù)據(jù)庫默認值操作
這篇文章主要介紹了Spring?boot?Jpa添加對象字段使用數(shù)據(jù)庫默認值操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11Java中的字節(jié),字符輸出流與字節(jié)和字符輸入流的簡單理解
這篇文章主要介紹了java 字節(jié)流和字符流的區(qū)別詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2021-07-07