【问题标题】:Better way to write the checkOrElseThrow generic function编写 checkOrElseThrow 泛型函数的更好方法
【发布时间】:2020-07-16 23:50:38
【问题描述】:

我有两个函数调用 Employee 和 Address DAO 类,我检查员工姓名或地址是否已被使用

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

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"));
}
AddressDAO.java中的

checkAndReturnAddress

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

问题

我的解决方案运行良好,但我想知道是否有其他更好的方法来重写我编写的通用函数 (checkOrElseThrow)

【问题讨论】:

  • employee.getAddressName() != null 如何检查“地址已被使用”?您不是在检查数据库以查看该地址是否已被其他员工使用。

标签: java lambda java-8 throwable supplier


【解决方案1】:

最好的写法是不要。

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

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

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

【讨论】:

  • 别忘了检查员工的可空性
  • @mstzn 原始代码也没有检查。
  • 怎么样Optional.ofNullable(carDO) .filter(e -&gt; e.getAddressName() != null) .orElseThrow(() -&gt; new EntityNotFoundException("Employee already in use for another address"));
  • 与简单、常规的 Java 相比,这给了你什么?
  • 由于Optional.ofNullable(employee) .filter(e -&gt; e.getAddressName() != null),它对employeee.getAddressName 进行空值检查,并在一行中返回Employee 对象
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

    由于问题更多的是围绕通用实现,您可以修改现有实现以使用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"));
    }
    

    【讨论】:

    • 现在看起来不需要通用函数,因为我们正在检查函数中的空值。怎么样Optional.ofNullable(carDO) .filter(e -&gt; e.getAddressName() != null) .orElseThrow(() -&gt; new EntityNotFoundException("Employee already in use for another address"));
    • @AlexMan 当您可以同时执行public Employee checkAndReturnEmployee(Employee employee) throws EntityNotFoundException { return checkOrElseThrow(employee, emp -&gt; emp.getAddressName().equals("success"), () -&gt; new EntityNotFoundException("Employee already in use for another address")); } 和当前的null 检查时,通用方法的实际值将会演变。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-21
    • 2022-01-28
    相关资源
    最近更新 更多