封装了一个相当于语法糖的异常处理办法,做个记录。
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;
}
}
网友评论