Lombok @SneakyThrows 注解:简化异常操作
一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 - 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/
截止目前, 星球 内专栏累计输出 72w+ 字,讲解图 3103+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2400+ 小伙伴加入学习 ,欢迎点击围观
大家好,我是小哈~
本小节中,我们来学习 Lombok 库中的 @SneakyThrows
注解。
什么是 @SneakyThrows ?
@SneakyThrows
用来 “偷偷地” 抛出检查型异常(checked exception),而无需显式地在方法签名中声明throws
或者使用try-catch
。对于需要捕获或声明的异常,@SneakyThrows
注解可以让方法绕过这一步。
示例代码
为了方便你理解它的作用,先来看一段示例代码:
import java.io.UnsupportedEncodingException;
/**
* @author: 犬小哈
* @date: 2024/11/5 23:09
* @version: v1.0.0
* @description: TODO
**/
public class SneakyThrowsExample {
/**
* 字节转字符串,且指定了字符编码为 UTF-8
* @param bytes
* @return
*/
public static String utf8ToString(byte[] bytes) {
try {
return new String(bytes, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
System.out.println(utf8ToString("犬小哈教程".getBytes()));
}
}
new String(bytes, "UTF-8")
需要显示的进行 try-catch
异常捕获,或者如下所示,通过 throws
将异常抛出去,让调用者去处理:
/**
* 字节转字符串,且指定了字符编码为 UTF-8
* @param bytes
* @return
*/
public static String utf8ToString(byte[] bytes) throws UnsupportedEncodingException {
return new String(bytes, "UTF-8");
}
有了 Lombok 的 @SneakyThrows
注解后,代码就可以精简成下面这样:
import lombok.SneakyThrows;
/**
* @author: 犬小哈
* @date: 2024/11/5 23:09
* @version: v1.0.0
* @description: TODO
**/
public class SneakyThrowsExample {
/**
* 字节转字符串,且指定了字符编码为 UTF-8
* @param bytes
* @return
*/
@SneakyThrows
public static String utf8ToString(byte[] bytes) {
return new String(bytes, "UTF-8");
}
public static void main(String[] args) {
System.out.println(utf8ToString("犬小哈教程".getBytes()));
}
}
在上面的代码中,方法中没有主动 try-catch
异常,也没有在方法签名中声明 throws
,而是在方法上添加了@SneakyThrows
注解,此注解会在编译期自动将抛出异常的工作做好,从而让开发者在代码中避免显式的 try-catch
块或 throws
声明。
为了验证这一点,可以看看 /target/classes
文件夹中编译后的代码,如下:
优缺点
-
优点:
-
减少了方法签名中的异常声明,保持代码简洁。
-
避免了过多的样板代码(如
try-catch
块)。 -
在某些情况下,提升了代码的可读性,尤其是对于 Lambda 表达式,示例代码如下:
List<String> list = Arrays.asList("file1.txt", "file2.txt"); list.forEach(@SneakyThrows file -> { Files.readAllLines(Paths.get(file)); });
-
-
缺点:
- 可读性与维护性:尽管简洁,
@SneakyThrows
可能会降低代码的可读性,特别是对于团队开发来说,后续维护人员需要了解注解的行为及其影响。 - 隐式异常抛出:
@SneakyThrows
隐藏了异常抛出的细节,可能导致程序在运行时抛出未经预料的异常,增加了调试的复杂性。 - 错误处理:这种 “偷懒” 的方式可能导致开发者忽视良好的错误处理实践。如果一个方法默默抛出异常,调用者在使用时无法有效地处理异常。
- 可读性与维护性:尽管简洁,
何时应慎用?
在生产环境中,@SneakyThrows
应该谨慎使用。虽然它减少了样板代码,但也容易掩盖程序的潜在问题。对于关键系统,显式声明异常可以帮助程序员更好地理解代码的边界和行为。
例如,在设计公共 API 时,使用 @SneakyThrows
可能会使接口使用者难以预料方法可能抛出的异常类型。最好在这种情况下显式声明异常,确保代码的透明度和文档性。
结语
@SneakyThrows
是一个便利但有争议的工具,它可以显著减少代码量,提高开发效率,但也容易导致代码不够直观。在日常开发中,建议在清楚其行为及影响的前提下使用它。适度使用 @SneakyThrows
,在适当的场景下,它是提升代码简洁度的好帮手;但在需要严格控制异常处理的地方,显式声明和处理异常仍然是更好的选择。