从 Optional.ifPresent() Java 抛出异常 8

Throw Exception from Optional.ifPresent() Java 8

我正在尝试从 Java 中的可选 API 的可选 ifPresent() 方法中抛出异常 8. 我正在检查是否存在对象,如果存在则检查它是否包含特定值,即包含状态 Pending。如果是,则抛出异常,否则抛出异常 return 对象,如果可选为空,也抛出异常,即 dbUser 为空,然后抛出异常,没有找到用户

这是我的代码:

Optional<User> dbUser = userRepository.findByEmail(email);

logger.info("Fetched user : " + dbUser + " by " + email);

logger.info("Fetched user status : " + dbUser.get().getStatus());

if (dbUser.isPresent()) {
    if (dbUser.get().getStatus().equals(Status.PENDING)) {
        throw new UserException("pending", email);
    }
}

上面的代码工作正常,但这种方法好吗?

当然,也许只需添加:

if (dbUser.isPresent() && dbUser.get().getStatus() != null ) {
     if (dbUser.get().getStatus().equals(Status.PENDING)) {
          throw new UserException("pending", email);
     }
}

异常通常应为特殊情况保留,并且用户处于待处理状态似乎是经常发生的事情,因此我更愿意 return 一个可选值(假设您在一个函数中 returns something, you didn't state the enclosing function).但是,根据上下文,您的方式也可以接受。

此外,如果您为挂起状态抛出异常,您可能还应该为不存在的用户和没有状态的用户抛出一个异常,如果可能的话,但我假设您没有说明这一点简洁并专注于手头的事情。

用户不存在,是否需要抛出异常? 可以使用google的guava包;

   User dbUser = userRepository.findByEmail(email);
   Preconditions.checkNotNull(dbUser, "user not exists!"); 
   logger.info("Fetched user : " + dbUser + " by " + email);
   logger.info("Fetched user status : " + dbUser.get().getStatus());
   Precondtions.checkArgument(!Status.PENDING.equals(dbUser.getStatus()), "user status is pending");

A Java 8 形式可以是:

if (dbUser.map(User::getStatus)
          .filter(Status.PENDING::equals)
          .isPresent()) {
    throw new UserException("pending", email);
}

这是在 Java-8 兼容 Optional 中重写的完全相同的代码:

User dbUser = userRepository.findByEmail(email)                     // Optional<User>
                            .filter(u -> !Status.PENDING.equals(u)) // Optional<User>
                            .orElseThrow(() ->                      // User or UserException
                                 new UserException("pending", email));

注意事项如下:

  • 记录的语句 dbUser.get().getStatus() 可能会抛出 NoSuchElementException
  • 我宁愿记录结果:

    User dbUser = userRepository.findByEmail(email)
                                .filter(u -> !Status.PENDING.equals(u))
                                .orElseThrow(() -> {
                                    logger.warn("Fetched user is pending: " + email);
                                    return new UserException("pending", email)
                                });
    
    logger.info("Fetched user=" + dbUser.getId() + ", status=" + dbUser.getStatus());
    

这个只是检查状态是否为挂起并抛出异常

userRepository.findByEmail(email).filter(u -> u.getStatus().equals(Status.PENDING))
                .ifPresent(u -> {
                    throw new UserException("pending", email);
                });

如果您想 return 一个用户,但如果状态为未决则抛出异常

User user = userRepository.findByEmail(email).filter(u -> !u.getStatus().equals(Status.PENDING))
.orElseThrow(() -> new UserException("pending", email));