可选isPresent vs orElse(null)

我在我的项目中更新了Spring 8的依赖项,并被编译错误轰炸,其中findOne()的方法定义已被findById()替换,现在返回一个Optional (如果我错了,请纠正我)。

在重构的过程中,我遇到了多种我可以选择采用的方法,因此我想要一些关于哪一种是首选的输入。

第一种方法:

 ExpectedPackage ep = expectedPackageRepository.findById(1).orElse(null); if(ep != null){ ep.setDateModified(new Date()); expectedPackageRepository.saveAndFlush(ep); } 

第二种方法:

 Optional ep = expectedPackageRepository.findById(1); if(ep.isPresent()){ ep.get().setDateModified(new Date()); expectedPackageRepository.saveAndFlush(ep.get()); } 

或者,我错过了第三种更好的方法吗? 我经历了几个问题和几篇文章,但我没有找到明确的答案。

你也可以这样做:

 expectedPackageRepository.findById(1).ifPresent( ep -> { ep.setDateModified(new Date()); expectedPackageRepository.saveAndFlush(ep); } ); 

理想情况下,您还可以将括号( {} )之间的部分提取到单独的方法中。 然后,你可以像这样写:

  expectedPackageRepository.findById(1).ifPresent(this::doSomethingWithEp); 

哪里:

 void doSomethingWithEp(ExpectedPackage ep) { ep.setDateModified(new Date()); expectedPackageRepository.saveAndFlush(ep); } 

您可以在此处阅读ifPresent的文档: https : ifPresent

如它所述,如果值存在,它将执行指定的操作,否则不执行任何操作。

另一个答案基本上是对你的第二种方法的一些重构,这本身没有任何错误,这只是一种风格问题。 当然,链接和提取到一个单独的方法将使这更加可读和清晰,毫无疑问(+1来自我),特别是因为正确使用ifPresent

我只是在这里添加get ,好吧,被视为某种设计错误(或者可能是一个糟糕的方法名称,可能来自guava心态)。 使用get即使它记录为在缺少该值时抛出exception也有点奇怪(如果你认为getter在这里,你不会指望getter抛出exception)。 并且你不会期望 isPresent 之后需要调用isPresent ,至少在与Optional第一次交互时不需要调用。 因此get建议被弃用(并且希望被删除),因此java-10添加了一个更好的加法orElseThrow() – 这在您阅读之后就有意义,因为抛出部分是在方法的名称中,所以没有惊喜。

此外,有人应该告诉你使用new Date() ,当与java-8中的Optional使用时看起来很奇怪,已经有更好的时间/日期相关类了。

我也不太确定为什么要手动更新修改日期,当有像PreUpdate/PrePersist这样的弹簧注释时。

是的,还有其他方法。

如果你绝对希望总有一个值,那么如果出现null,则使用Optional::orElseThrow抛出exception。

如果您希望null可能到达,并且有一个替代实例可用作后备选项,请使用Optional::orElse

如果没有后备实例,但您有一个函数可以调用以提供后备实例,请使用Optional::orElseGet

如果您不关心接收null,并且在null到达时想要什么都不做,请使用Optional::ifPresent 。 如果值到达,则传递要运行的代码块。

如果您只关心符合某些要求的值,请使用Optional::filter 。 传递定义您的要求的Predicate 。 例如,我们只关心一个Optional< String >包含文本, 并且该文本中包含单词purplemyOptional.filter( s -> s.contains( "purple" ) ).ifPresent( this::print ) ; 。 如果收到null,则不会发生我们所需的操作(在此示例中调用print )。 如果收到一个值但未能满足我们的谓词,我们所希望的操作永远不会发生。


if( myOptional.isPresent() ) { SomeClass x = myOptional.get() ; … } if( myOptional.isPresent() ) { SomeClass x = myOptional.get() ; … }是有效的,也是安全的。 但这不是Optional的原始意图,因为它与执行旧式null检查if ( null == x ) { … } 。 关于Optional的其他方法提供了一种更清晰,更优雅的方式来表达您对可能的空到达的意图。

你也可以这样做:

 Optional updatedPackage = expectedPackageRepository.findById(1).map(ep -> { ep.setDateModified(new Date()); return expectedPackageRepository.saveAndFlush(ep); });