关于@SneakyThrows使用

关于@SneakyThrows注解的使用,主要是消除代码中异常处理代码.

1 异常引入

Java中异常Throwable分为两类, 一种是Exception类,称为受检异常(Checked Exception), 第二种是RuntimeException类, 运行时异常.

Exception类异常,强制要求方法抛出可能出现的异常,调用者必须处理这个异常. 一般在代码中,程序员通过捕获异常,再包一层RuntimeException,向外抛出.(常见如Spring源码中)

2 @SneakyThrows

1 SneakyThrows注解的源码
@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.SOURCE)
public @interface SneakyThrows {
	/** @return The exception type(s) you want to sneakily throw onward. */
	Class<? extends Throwable>[] value() default java.lang.Throwable.class;
	
	//The fully qualified name is used for java.lang.Throwable in the parameter only. This works around a bug in javac:
	//   presence of an annotation processor throws off the type resolver for some reason.
}
2使用案例
public class SneakyThrowDemo {

    // 方法主动声明可能出现的异常
    public void test1() throws IllegalAccessException, InstantiationException {
        SneakyThrowDemo sneakyThrowDemo = SneakyThrowDemo.class.newInstance();
    }

    // 使用SneakyThrows注解
    @SneakyThrows
    public void test2() {
        SneakyThrowDemo sneakyThrowDemo = SneakyThrowDemo.class.newInstance();
    }

    // test2方法的编译结果
    public void test3() {
        try {
            SneakyThrowDemo sneakyThrowDemo = SneakyThrowDemo.class.newInstance();
        } catch (Throwable e) {
            // 调用Lombok方法转化为RuntimeException
            throw Lombok.sneakyThrow(e);
        }
    }

}

其中Lombok.sneakyThrow()方法

	/**
	 * Throws any throwable 'sneakily' - you don't need to catch it, nor declare that you throw it onwards.
	 * The exception is still thrown - javac will just stop whining about it.
	 * <p>
	 * Example usage:
	 * <pre>public void run() {
	 *     throw sneakyThrow(new IOException("You don't need to catch me!"));
	 * }</pre>
	 * <p>
	 * NB: The exception is not wrapped, ignored, swallowed, or redefined. The JVM actually does not know or care
	 * about the concept of a 'checked exception'. All this method does is hide the act of throwing a checked exception
	 * from the java compiler.
	 * <p>
	 * Note that this method has a return type of {@code RuntimeException}; it is advised you always call this
	 * method as argument to the {@code throw} statement to avoid compiler errors regarding no return
	 * statement and similar problems. This method won't of course return an actual {@code RuntimeException} -
	 * it never returns, it always throws the provided exception.
	 * 
	 * @param t The throwable to throw without requiring you to catch its type.
	 * @return A dummy RuntimeException; this method never returns normally, it <em>always</em> throws an exception!
	 */	
public static RuntimeException sneakyThrow(Throwable t) {
		if (t == null) throw new NullPointerException("t");
		return Lombok.<RuntimeException>sneakyThrow0(t);
	}

	// 对返回参数做了强转为T类型
	private static <T extends Throwable> T sneakyThrow0(Throwable t) throws T {
		throw (T)t;
	}

整个处理过程中, 最重要的是throw (T)t, 使用泛型,将传入的Throwable强转为RuntimeException异常.

虽然, 我们抛出的异常不是RuntimeException,但是可以骗过javac编译器,泛型最后存储为字节码文件时并没有泛型信息.

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值