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