当我需要在Optional.orElse()上使用Optional.orElseGet()时

我需要对此作出明确的解释,即使我读到这个关于差异的链接 ,但没有明确的清晰度。 所以任何人都可以用代码向我解释这一点。

我想我开始明白你的问题。 使用Optional执行顺序可能与我们在过程编程中使用的顺序不同(Java流和使用lambdas的其他代码也是如此)。

我将使用Eugene的答案中的两个例子:

  o1.orElse(new MyObject()); // 1055e4af 

这是普通的旧Java:它是对orElse()的调用,将new MyObject()作为参数。 因此首先评估参数并创建一个新的MyObject 。 然后将其传递给orElse()orElse()查看Optional是否存在值; 如果是这样,它返回该值(丢弃新创建的对象); 如果没有,它返回参数中给定的对象。 这是一个更简单的例子。

  o1.orElseGet(() -> { System.out.println("Should I see this"); return new MyObject(); }); 

我们再次使用一个参数进行方法调用,并再次首先计算参数。 lambda仅作为供应商创建和传递。 { }内的代码尚未执行(你也看不到Should I see this在Eugene的输出中Should I see this )。 再次, orElseGet会查看orElseGet是否存在值。 如果有,则返回该值,并忽略我们传递的供应商。 如果没有,则调用供应商,执行{ }内的代码以获取从orElseGet()返回的值。

在第一种情况下,可以说创建并浪费了MyObject 。 第二,创建和浪费了Supplier 。 你得到的回报是两种情况下的简洁和空指针安全代码。 所以你选择哪一个并不重要。 如果创建MyObject代价高昂或者有不必要的副作用,那么您当然需要第二个版本,其中对象仅在被请求时创建,并且永远不会浪费。 注释中的Eugene提到了返回的对象来自数据库调用的情况。 数据库调用通常非常耗时,您不希望出于任何目的。

一个例子怎么样:

 static class MyObject { public MyObject() { System.out.println("Creating one..." + this); } } 

一些用法:

  Optional o1 = Optional.of(new MyObject()); // 7382f612 o1.orElse(new MyObject()); // 1055e4af o1.orElseGet(() -> { System.out.println("Should I see this"); return new MyObject(); }); 

还有一些输出:

  Creating one... MyObject@7382f612 Creating one... MyObject@1055e4af 

如果Optional 有值 ; orElse仍然被调用但未被使用。 关于矛盾orElseGet没有被称为。

考虑创建对象昂贵的情况; 你会用哪一个?

它实际上更容易理解我认为如果你查看代码:

 public T orElseGet(Supplier supplier) { return value != null ? value : supplier.get(); }