我需要对此作出明确的解释,即使我在差异上阅读link但没有明确的清晰度。因此,任何人都可以通过代码向我解释这一点。
答案 0 :(得分:30)
我想我开始明白你的问题。 Optional
的执行顺序可能与我们在程序编程中使用的顺序不同(Java流和使用lambdas的其他代码也是如此)。
我将使用Eugene’s answer中的两个示例:
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仅作为供应商创建和传递。 { }
中的代码尚未执行(您在Eugene的输出中也看不到Should I see this
)。再次orElseGet
查看Optional
中是否存在值。如果有,则返回该值,并忽略我们传递的供应商。如果没有,则调用供应商,执行{ }
内的代码以获取从orElseGet()
返回的值。
在第一种情况下,可以说创建了MyObject
并浪费了。在第二个中,创建了Supplier
并浪费了。你得到的回报是两种情况下的简洁和空指针安全代码。所以你选择哪一个并不重要。如果创建MyObject
代价高昂或者有不必要的副作用,那么您当然需要第二个版本,其中仅在需要时才创建对象,并且永远不会浪费。评论中的Eugene提到了返回的对象来自数据库调用的情况。数据库调用通常非常耗时,您不希望出于任何目的。
答案 1 :(得分:12)
示例如何:
static class MyObject {
public MyObject() {
System.out.println("Creating one..." + this);
}
}
还有一些用法:
Optional<MyObject> 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<? extends T> supplier) {
return value != null ? value : supplier.get();
}
答案 2 :(得分:1)
回答here,当所需资源的获取成本昂贵时,您可能要考虑第二种方法。
// Always get heavy resource
getResource(resourceId).orElse(getHeavyResource());
// Get heavy resource when required.
getResource(resourceId).orElseGet(() -> getHeavyResource())