JDK8 Functional Programming一个函数可以抛出异常吗?

时间:2018-09-24 15:22:58

标签: java-8 functional-programming

我有一个要求

  1. 从员工存储库中获取员工信息。
  2. 使用一些其他信息更新员工信息。
  3. 将员工对象转换为gatewayRequest对象。
  4. 呼叫网关服务并获得响应。
  5. 从响应中获取网关调用的返回码。

为此,我正在使用函数式编程来实现结果。

在这里我已经在服务层中创建了多个功能

final Function<String, Employee> getRegisteredEmployee =
        localId -> employeeRepository.findById(employeeId).
                orElseThrow(() -> new ResourceNotFoundException("ResourceNotFound"));

final Function<Employee, Employee> updateEmployeAddressandSave =
        employe -> {
            String status = //some logic to identitythe Employee
            Employee e = new Employee(employee.getName(),employee.getAddress ,"INTERNAL_EMPLOYEE")
            Employee emp = employeeRepository.save(e);
            return emp;
};

同样,我创建了不同的函数,然后使用功能接口的andThen方法获取结果

getRegisteredEmployee.
       andThen(updateEmployeAddressandSave).
       andThen(transformTheEmployeeToGatewayRequest).
       andThen(allgateWayClinet).apply(12);

根据函数编程模型,一个函数应该接受输入并给出一些输出;它不应引发任何异常。但是在我的示例中,getRegisteredEmployee如果找不到雇员,则会引发异常。

因此,我是否不遵循函数式编程的核心原则?

在函数式编程中抛出异常的替代方法是什么?

2 个答案:

答案 0 :(得分:1)

虽然不遵循原则,但从技术上讲,可以创建一个将引发已检查异常的功能接口。

@FunctionalInterface
interface CheckedFunction<A, B> {
  B apply(A a) throws Exception;
}

(由于您使用的是andThen,因此还需要使用default关键字来实现。不过请记住,功能接口最多必须具有一个非默认方法,因此您必须提供默认的andThen实现。)

因此,举例来说,您将可以执行以下操作:

public void doThings(Integer id) throws Exception {

    CheckedFunction<Integer, Employee> fn = (id) -> someMethodThatReturnsAnEmployeeOrThrows(id);

    fn.apply(id)
      .map( ... ) // ... some other stuff

}

正如我所提到的,这不遵守原则;我只在绝对必须冒起例外时才走这条路。在这种情况下,其他Java 8功能,例如Optional更合适。 (由于看起来您正在使用spring的JPA实现,因此可以定义findById方法来返回Optional<Employee>。)

答案 1 :(得分:0)

方法getRegisteredEmployee可以返回Optional对象,而不是引发异常。

 final Function<String, Employee> getRegisteredEmployee =
        localId -> employeeRepository.findById(employeeId);

final Function<Employee, Employee> updateEmployeAddressandSave =
        employe -> {
            if(employe.isPresent()) {
                employe.get();
               ...
               String status = //some logic to identitythe Employee
               Employee e = new Employee(employee.getName(),employee.getAddress ,"INTERNAL_EMPLOYEE")
               Employee emp = employeeRepository.save(e);
               return new Optional(emp);
            } else {
               return Optional.empty();
            }
};

etc...