zoukankan      html  css  js  c++  java
  • Java: 帮助Checked Exception通过Unchecked Exception通道的技术

      最近用到了Java的异步框架,名叫Future。它通常是与λ表达式结合来使用的。λ表达式是通过某类注解(接口)定义 的。但是看了类似java.lang.Runnable.run()这些方法都没有定义throws,也就是意味着它不支持抛出受检异常(checked exception)。

      我采取了一个方案,自己捕获受检异常,并把它保存到一个集合中。在各个异步任务都结束的时候检查这个集合,如果非空则进行回滚操作。这个方案的缺点是,与异步框架结合的不够好。有受检异常发生时,不会自动取消后续的异步任务。

      能不能把所有的受检异常都变成非受检异常(unchecked exception)呢?就是说,在一个受检异常发生时,第一时间就把它变成非受检异常。从而实现整个系统中的受检异常在尽可能小的范围内发生和传播。或许JDK也希望我们这么做,不然为什么这些与Future紧密相关的λ表达式都不支持受检异常呢。鉴于现有的代码以及大量的组件都使用了受检异常。如果都转为非受检异常,势必要改造很多个类,既有工作量也有挑战,暂且不能这么干。

      能不能做一个隧道,帮助受检异常顺利的通过不支持受检异常的通道,并在通过后对其进行恢复。示意图如下。


      经过实验,这个方案是可行的。我封装了一个类来做这件事,代码如下。

    public class CheckedExceptionWrapperException extends RuntimeException {
    
        public CheckedExceptionWrapperException(String message, Throwable ex) {
            super(message, ex);
        }
        
        public static CheckedExceptionWrapperException wrap(String message, Excepton ex) {
            if (ex isinstanceof CheckedExceptionWrapperException) {
                return (CheckedExceptionWrapperException) ex;
            }
            return new CheckedExceptionWrapperException(message, ex);
        }
        
        public static Excepton unwrap(Excepton ex) {
            if (ex isinstanceof CheckedExceptionWrapperException) {
                return ((CheckedExceptionWrapperException) ex).unwrap();
            }
            return ex;
        }
        
        public Excepton unwrap() {
            return this.getInnerExeption();
        }
    }

    用法举例

    import java.util.concurrent.CompletableFuture;
    
    task1 = CompletableFuture.runAsyn(() -> {
        try {
            doSomeThing1();
        } catch(Excepton ex) {
            throw CheckedExceptionWrapperException.wrap(ex);
        }
    });
    task2 = task1.thenRun(() -> {
        try {
            doSomeThing2();
        } catch(Excepton ex) {
            throw CheckedExceptionWrapperException.wrap(ex);
        }
    });
    task3 = CompletableFuture.runAsyn(() -> {
        try {
            doSomeThing3();
        } catch(Excepton ex) {
            throw CheckedExceptionWrapperException.wrap(ex);
        }
    });
    task4 = task3.thenRun(() -> {
        try {
            doSomeThing4();
        } catch(Excepton ex) {
            throw CheckedExceptionWrapperException.wrap(ex);
        }
    });
    try {
        CompletableFuture.all(task2, task4).get();
    } catch(Excepton ex) {
        throw CheckedExceptionWrapperException.unwrap(ex);
    }

      达到的效果就是无论发生受检异常还是非受检异常,都能够利用异步框架的机制,取消后续任务的执行。能够利用异步框架进行传播,并在需要的时候进行恢复(抛出与捕获),恢复后能得到原始的调用栈。

      实际使用时发现异步框架在捕获到异常时,还会再包装一层它自己的异常,所以我也在这个类中对这一层进行解包装。代码如下。

    public class CheckedExceptionWrapperException extends RuntimeException {
        // ...
        public static Excepton unwrap(Excepton ex) {
            if (ex isinstanceof java.util.concurrent.CompletionException) {
                return unwrap(ex.getInnerExeption())
            }
            if (ex isinstanceof CheckedExceptionWrapperException) {
                return ((CheckedExceptionWrapperException) ex).unwrap();
            }
            return ex;
        }
        // ...
    }

       我把这项技术称作为异常隧道。这个隧道帮助受检异常通过了原本通不过的通道。有了这个异常隧道,终于可以好好地使用Future了。


    博主简介:佘焕敏(shé),洋名 Billy Sir。
    关注编程基础技术,并致力于研究软件的自动化生成。 对编程规范化、面向对象的极致使用也有着浓厚的兴趣。 同时非常希望能够写程序到65岁。
    只有工匠精神,才能把常人觉得单调乏味的代码,当作作品雕刻成艺术品。
  • 相关阅读:
    tiptop之4gl调试3/31
    打印空白3/31
    佛陀教育入门
    什么是佛教
    智、觉
    保持头脑清醒的窍门2/13
    php中将数组转换为指定符号分割的字符串
    kali下apche配置多网站
    php数组指定字段排序
    php 语句块耗时性能测试
  • 原文地址:https://www.cnblogs.com/BillySir/p/14829978.html
Copyright © 2011-2022 走看看