编写 checkOrElseThrow 通用函数的更好方法

Better way to write the checkOrElseThrow generic function

我有两个针对 Employee 和 Address DAO 的函数调用 class 我在其中检查员工姓名或地址是否已被使用

为了使检查和抛出异常变得通用,我创建了以下通用函数

checkOrElseThrowCommonUtil.java

public static <R, C, T extends Throwable> R checkOrElseThrow(R rtn, C chk, Supplier<? extends T> ex) throws T
{
    if (chk != null)
    {
        throw ex.get();
    }
    return rtn;
}

并且在 EmployeeDAO.javaAddressDAO.java 中调用了上述通用函数,如下所示

checkAndReturnEmployeeEmployeeDAO.java

public Employee checkAndReturnEmployee(Employee employee) {
    return checkOrElseThrow(
        employee,
        employee.getAddressName(),
        () -> new EntityNotFoundException("Employee already in use for another address"));
}

checkAndReturnAddressAddressDAO.java

public Address checkAndReturnAddress(Address address) {
    return checkOrElseThrow(
        address,
        address.getEmployeeName(),
        () -> new EntityNotFoundException("Address already in use for another address"));
}

问题

我的解决方案工作正常,但我想知道是否有任何其他更好的方法来重写我编写的通用函数 (checkOrElseThrow)

最好不要这样写。

public Employee checkAndReturnEmployee(Employee employee) {
    if (employee.getAddressName() == null) {
      throw new EntityNotFoundException("Employee already in use for another address"));
    }
    return employee;
}

上面的代码同样简短,但更具可读性。更清楚的是什么条件,不满足会怎样。

您的自定义函数仅用于尝试为 Java 创建一种其他人不会理解的新语法,您可能很快也会忘记。

考虑使用 java.util.Optional,因为您尝试实现的行为已经存在。我发现它比 if (smth != null) 检查要优雅得多。

Optional.ofNullable(employee)
    .map(Employee::getAddressName)
    .orElseThrow(() -> new EntityNotFoundException("Employee already in use for another address");

总的来说,我更喜欢Optional,主要是因为如果还需要对entity进行空检查,人们可能会嵌套多个if或链接条件(不是这种情况题)。然后你需要像 if (entity != null && entity.getAddress() == null) {throw ...} 这样的东西,它比带 Optional 的链式版本丑陋且可读性差得多。后一种说法,当然也有点句法味道了。

由于问题更多地围绕 通用实现 ,您可以修改现有的实现以利用 Predicate 来测试任何标准并计算出来如:

public <R, T extends Throwable> R checkOrElseThrow(R returnValue, Predicate<R> successCriteria,
                                                   Supplier<? extends T> ex) throws T {
    if (successCriteria.test(returnValue)) {
        return returnValue;
    }
    throw ex.get();
}

并在相应的地方进一步调用它:

public Employee checkAndReturnEmployee(Employee employee) throws EntityNotFoundException {
    return checkOrElseThrow(employee, emp -> emp.getAddressName() != null,
            () -> new EntityNotFoundException("Employee already in use for another address"));
}

public Address checkAndReturnAddress(Address address) throws EntityNotFoundException {
    return checkOrElseThrow(address, add -> add.getEmployeeName() != null,
            () -> new EntityNotFoundException("Address already in use for another address"));
}