检查 Optional 的布尔值并在 true 时抛出异常的最佳方法

Best way to check Optional's boolean value and throw exception if true

我有一个可为 null 的变量 id,通过它我可以通过 getLocationById(再次为 nullable)得到一个 Location
我要做的是if(id!=null && (location == null || location.isDeprecated())) => throw exception,否则什么都不做

以下是我能想到的方法(除了先取出布尔值然后在 if 语句后抛出异常)。但是当id为null时会抛出异常,这不是我想要的。

想知道是否有更好的方法? (我正在使用 Java17)


Optional.ofNullable(id).map(service::getLocationById)
      .filter(Predicate.not(Location::isDeprecated))
      .orElseThrow(()->new BadRequestException("Location is deprecated"))


EDIT1:我想我可以做以下事情,但如果有更好的想法就更好了:


Optional.ofNullable(id).map(service::getLocationById)
      .filter(Location::isDeprecated)
      .ifPresent(l->{ throw new BadRequestException("Location is deprecated");});

EDIT2:问完所有这些,我同意@Holger 在评论中使用旧的好方法提出的建议:

if(id != null) { 
  var loc = service.getLocationById(id); 
  if(loc != null && loc.isDeprecated()) 
    throw … 
}

因为

  1. 它也非常清晰易读
  2. 我的代码在热路径中,Optional 方式引入了开销和额外的堆分配。

使用 try catch 块。当你处理可能的异常时,就像你的情况一样,让事情变得简单。

这取决于你的风格和同事的风格。 当 location 为 null 时,第二个行为不同,因此它们不相同。要使其表现相似,您必须像这样调整它:

Optional.ofNullable(id).map(service::getLocationById)
  .or(()-> Optional.of(createLocationWithDeprecatedFlag()))
  .filter(Location::isDeprecated)
  .ifPresent(l->{ throw new BadRequestException("Location is deprecated");});

不太好。因此,就您而言,我建议您采用第一种方法。它是可读的,从我的角度来看很好理解。

选项不能替代条件,应该在有意义的时候使用,而不是不惜一切代价简单地避免条件。你的情况也可能或多或少是简单的 if,但这里可选的还不错。