一个基于 lambda 的异常处理工具类

封装了一个相当于语法糖的异常处理办法,做个记录。
PS:其实只是一个对于函数式编程方式的思考……
使用示例如下:

// 使用工具类
String message = ExceptionExecutor.<String>getInstance()
        .tryF(() -> "This is a message.")
        .success(s -> System.out.println("success, value=" + s))
        .catchF(Throwable::printStackTrace)
        .defaultF(() -> "This is a default message.")
        .finallyF(s -> System.out.println("In finally, return value=" + s))
        .execute();

// 传统 try catch finally
try {
    message = "This is a message.";
    System.out.println("success, value=" + message);
} catch (Exception e) {
    e.printStackTrace();
    message = "This is a default message.";
} finally {
    System.out.println("In finally, return value=" + message);
}

// -- with 系列
// 如果捕获一个异常,将返回 null
message = ExceptionExecutor.withTry(()->"This is a message.");
// 如果捕获一个异常,将会打印堆栈信息到Log框架
message = ExceptionExecutor.withLog(()->"This is a message.", log);
// 如果捕获一个异常,将会返回默认值
message = ExceptionExecutor.withDef(() -> "This is a message.", "This is a default message.");
// 如果执行成功,将会打印执行结果
message = ExceptionExecutor.withSuc(()->"This is a message.", System.out::println);
// 如果捕获一个异常,将会打印堆栈信息
message = ExceptionExecutor.withCatch(() -> "This is a message.", Throwable::printStackTrace);
// 执行 finally 代码块
message = ExceptionExecutor.withFinally(() -> "This is a message.", 
        s -> System.out.println("In finally, return value=" + s));

工具类代码如下:


import java.util.function.Consumer;
import java.util.function.Supplier;

/**
 * 使用 lambda 表达式简化处理异常代码
 *
 * @author frank
 * @date 2020-03-27 18:19
 */
public class ExceptionExecutor<T> {

    /**
     * 可能抛出异常的代码
     */
    private Callable<T> tryCallable;

    /**
     * 如果抛出异常将会返回的值,如果没有指定,抛出异常时将会返回 null
     */
    private Supplier<T> defaultSupplier;

    /**
     * 没有异常抛出时的后续代码
     */
    private Consumer<T> successConsumer;

    /**
     * 抛出异常时执行的代码
     */
    private Consumer<Throwable> catchConsumer;

    /**
     * 最终必然会执行的操作
     * 如果没有指定抛出异常会返回的值,该函数的参数值可能为 null,请注意在函数中处理
     */
    private Consumer<T> finallyConsumer;

    /**
     * 私有化构造,建议使用 getInstance() 方法获取实例
     */
    private ExceptionExecutor() {
    }

    /**
     * 获得对象实例
     *
     * @param <T> 如果需要泛型调用,使用 ExceptionExecutor.<T>getInstance() 调用。T 为泛型类名
     */
    public static <T> ExceptionExecutor<T> getInstance() {
        return new ExceptionExecutor<>();
    }

    // -- 某天,我意识到这个工具类是个画蛇添足的玩意儿,故创建了以下 with 系列静态方法……

    public static <T> T withTry(Callable<T> attemptCallable) {
        return ExceptionExecutor.<T>getInstance().tryF(attemptCallable).execute();
    }

    public static <T> T withLog(Callable<T> attemptCallable, org.slf4j.Logger log) {
        return ExceptionExecutor.<T>getInstance()
                .tryF(attemptCallable)
                .catchF(t -> log.error(t.getMessage(), t))
                .execute();
    }

    public static <T> T withDef(Callable<T> attemptCallable, T def) {
        return ExceptionExecutor.<T>getInstance()
                .tryF(attemptCallable)
                .defaultF(() -> def)
                .execute();
    }

    public static <T> T withSuc(Callable<T> attemptCallable, Consumer<T> successConsumer) {
        return ExceptionExecutor.<T>getInstance()
                .tryF(attemptCallable)
                .success(successConsumer)
                .execute();
    }

    public static <T> T withCatch(Callable<T> attemptCallable, Consumer<Throwable> errorConsumer) {
        return ExceptionExecutor.<T>getInstance()
                .tryF(attemptCallable)
                .catchF(errorConsumer)
                .execute();
    }

    public static <T> T withFinally(Callable<T> attemptCallable, Consumer<T> ultimateConsumer) {
        return ExceptionExecutor.<T>getInstance()
                .tryF(attemptCallable)
                .finallyF(ultimateConsumer)
                .execute();
    }

    public ExceptionExecutor<T> tryF(Callable<T> attemptCallable) {
        this.tryCallable = attemptCallable;
        return this;
    }

    public ExceptionExecutor<T> defaultF(Supplier<T> defaultValueSupplier) {
        this.defaultSupplier = defaultValueSupplier;
        return this;
    }

    public ExceptionExecutor<T> success(Consumer<T> successConsumer) {
        this.successConsumer = successConsumer;
        return this;
    }

    public ExceptionExecutor<T> catchF(Consumer<Throwable> errorConsumer) {
        this.catchConsumer = errorConsumer;
        return this;
    }

    public ExceptionExecutor<T> finallyF(Consumer<T> ultimateConsumer) {
        this.finallyConsumer = ultimateConsumer;
        return this;
    }

    /**
     * 执行所有可能的操作,并返回执行结果
     *
     * @throws IllegalArgumentException 如果没有指定 tryF 函数,将会抛出该异常
     */
    public T execute() {
        if (tryCallable == null) {
            throw new IllegalArgumentException("must set try supplier.");
        }
        T t = null;
        try {
            t = tryCallable.call();
            if (successConsumer != null) {
                successConsumer.accept(t);
            }
        } catch (Throwable e) {
            if (catchConsumer != null) {
                catchConsumer.accept(e);
            }
            if (defaultSupplier != null) {
                t = defaultSupplier.get();
            }
        } finally {
            if (finallyConsumer != null) {
                finallyConsumer.accept(t);
            }
        }
        return t;
    }

    /**
     * Copy of {@link java.util.concurrent.Callable}.
     * <p>
     * A task that returns a result and may throw an Throwable.
     * Implementors define a single method with no arguments called
     * {@code call}.
     */
    @FunctionalInterface
    public interface Callable<V> {
        /**
         * Computes a result, or throws an Throwable if unable to do so.
         *
         * @return computed result
         * @throws Throwable if unable to compute a result
         */
        V call() throws Throwable;
    }

}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

友情链接更多精彩内容