通常,我们在写后端业务逻辑时,可能会存在多处,像如下断言式的校验代码,在不满足条件时,即时中断业务:
public static void main(String[] args) {
// 伪代码
// 业务判空
if (xxx == null) {
throw new RuntimeException("xxx 不能为空");
}
....
// 模拟转账业务
BigDecimal balance = new BigDecimal(100);// 查询数据库的转账人余额
BigDecimal transfer = new BigDecimal(50);// 订单转出金额
if (balance.compareTo(transfer) == -1) {
throw new RuntimeException("钱不够!");
}
....
// 模拟限制次数业务
Integer count = 3; // 查询到的当前操作次数
Integer limit = 3; // 查询到的最大限制次数
if (count >= limit) {
throw new RuntimeException("已达次数上限");
}
....
}
少量写起来倒也无妨,但一旦校验的东西多了,这种校验代码就会变得又臭又长,阅读时,也需费时思考校验的逻辑。
于是,我们来定义一个Assert工具类来消除该重复,简化校验逻辑。
/**
* 断言工具类
*
* @Author zaiLuShang
*/
public class Assert {
private Assert() {
}
public static <T, E extends RuntimeException> void isTrue(T t, Predicate<T> verifier, Supplier<E> exSupplier) {
// 断言结果
boolean asserted = verifier.test(t);
// 断言未通过
if (!asserted) throw exSupplier.get();
}
public static <T, E extends RuntimeException> void isTrue(T caller, T reference, BiPredicate<T, T> verifier, Supplier<E> exSupplier) {
// 断言结果
boolean asserted = verifier.test(caller, reference);
// 断言未通过
if (!asserted) throw exSupplier.get();
}
/**********************************************以下为断言时的常用方法,提供静态方法引用 **********************************************/
// 对象为空
public static <T> Boolean isNull(T t) {
return Objects.isNull(t);
}
// 对象非空
public static <T> Boolean isNotNull(T t) {
return Objects.nonNull(t);
}
// 比较后相等
public static <T extends Comparable<T>> Boolean isEq(T caller, T reference) {
return caller.compareTo(reference) == 0;
}
// 比较后大于
public static <T extends Comparable<T>> Boolean isGt(T caller, T reference) {
return caller.compareTo(reference) == 1;
}
// 比较后大于等于
public static <T extends Comparable<T>> Boolean isGe(T caller, T reference) {
return caller.compareTo(reference) >= 0;
}
// 比较后小于
public static <T extends Comparable<T>> Boolean isLt(T caller, T reference) {
return caller.compareTo(reference) == -1;
}
// 比较后小于等于
public static <T extends Comparable<T>> Boolean isLe(T caller, T reference) {
return caller.compareTo(reference) <= 0;
}
}
使用时,只需如下:
public static void main(String[] args) {
// 异常抽取为供给型函数式接口,可以定制异常
// 单个对象判空
Assert.isTrue(null, Assert::isNotNull, () -> new RuntimeException("要求非空"));
Assert.isTrue(1, 1, Assert::isEq, () -> new MyRuntimeException("要求相等"));
Assert.isTrue(1f, 2f, Assert::isGt, () -> new YourRuntimeException("要求大于"));
Assert.isTrue(new Date(), new Date(), Assert::isLt, () -> new HisRuntimeException("要求小于"));
Assert.isTrue(1l, 2l, Assert::isLe, () -> new HerRuntimeException("要求xxx"));
Assert.isTrue(1d, 2d, Assert::isLe, () -> new RuntimeException("要求xxx"));
Assert.isTrue(new BigDecimal(1), new BigDecimal(2), Assert::isLe, () -> new RuntimeException("要求xxx"));
....
}
代码变得干净又卫生。