@SneakyThrows注解

@SneakyThrows注解

  • @SneakyThrows注解的用途得从java的异常设计体系说起

  • 这是异常的类图

  • Throwable是Error和Exception的父类,用来定义所有可以作为异常被抛出来的类。 UML图如下:

Error和Exception区分:

  • Error是编译时错误和系统错误,系统错误在除特殊情况下,都不需要你来关心,基本不会出现。而编译时错误,如果你使用了编译器,那么编译器会提示。

  • Exception则是可以被抛出的基本类型,我们需要主要关心的也是这个类。

  • Exception又分为RunTimeException和其他Exception。

RunTimeException和其他Exception区分:

  • 其他Exception,受检查异常。可以理解为错误,必须要开发者解决以后才能编译通过,解决的方法有两种

    • throw到上层

    • try-catch处理

  • RunTimeException:运行时异常,又称不受检查异常,不受检查,因为不受检查,所以在代码中可能会有RunTimeException时Java编译检查时不会告诉你有这个异常,但是在实际运行代码时则会暴露出来,比如经典的1/0,空指针等。如果不处理也会被Java自己处理

@SneakyThrows的作用:

  • 普通Exception类,也就是我们常说的受检异常或者Checked Exception会强制要求抛出它的方法声明throws,调用者必须显示的去处理这个异常。设计的目的是为了提醒开发者处理一些场景中必然可能存在的异常情况。比如网络异常造成IOException

  • 但是现实大部分情况下的异常,我们都是一路往外抛了事。所以渐渐的java程序员处理Exception的常见手段就是外面包一层RuntimeException,接着往上丢

  • 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强转为RuntimeException。虽然事实上我们不是RuntimeException。但是没关系。因为JVM并不关心这个。泛型最后存储为字节码时并没有泛型的信息。这样写只是为了骗过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;
        }

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
@RedisLock 和 @Transactional 是两个在代码中使用的注解。 @RedisLock 是一个自定义注解,用于在代码中实现分布式锁的功能。在引用和引用[2]的代码中,可以看到在执行某个方法之前先获取了一个分布式锁(redisLock.lock(id)),如果获取锁成功,则执行该方法的业务逻辑,然后释放锁(redisLock.unlock(id))。如果获取锁失败,则抛出异常表示当前操作无法进行。这样可以确保在分布式环境中同一时间只有一个线程能够执行被锁定的代码块。 @Transactional 是一个用于事务管理的注解。它可以用于类或方法上,用于标识需要被事务管理的代码块。在引用和引用的代码中,可以看到被 @Transactional 注解标记的方法表示该方法需要在事务中执行。在事务中,可以保证一系列的数据库操作要么全部成功提交,要么全部失败回滚。 需要注意的是,在引用中提到的一个问题是,当 @RedisLock 和 @Transactional 注解同时存在时,可能会导致分布式锁失效。因为事务的提交是在分布式锁释放之后进行的,这意味着在事务提交前,分布式锁已经被释放,可能导致其他线程获取到锁并同时执行被锁定的代码块。因此,在使用 @RedisLock 和 @Transactional 注解时需要特别注意这个问题,并确保在代码中正确处理分布式锁和事务的顺序。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [【Redis】Redis分布式锁的10个坑](https://blog.csdn.net/u011397981/article/details/130490197)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [java中锁与@Transactional同时使用导致锁失效的问题](https://blog.csdn.net/weixin_42134685/article/details/127090804)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT枫斗者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值