我对Java可选属性的评估有些麻烦。考虑以下测试:
@Test
public void test() {
System.out.println("GOT STRING: " + first().orElse(second()));
}
private Optional<String> first() {
System.out.println("Evaluating first");
return Optional.of("STRING OPTIONAL");
}
private String second() {
System.out.println("Evaluating second");
return "SECOND STRING";
}
我的期望是,由于first()返回一个非空的Optional,因此第二个不被评估。但实际上输出是:
Evaluating first
Evaluating second
GOT STRING: STRING OPTIONAL
在测试中尝试使用orElse中使用的功能:
@Test
public void test2() {
System.out.println("GOT STRING: " + (first() != null ? "FIRST IS NOT NULL" : second()));
}
输出:
Evaluating first
GOT STRING: FIRST IS NOT NULL
为什么要评估第二个选项?这好像不好吗?
最佳答案
因为您正在调用second()
方法,所以为了将值提供为orElse()
的参数。参数的值将被忽略(因为您已经有一个值),但这并不意味着不必提供它。
基本上,这段代码:
first().orElse(second())
等效于:
Optional<String> tmp1 = first();
Optional<String> tmp2 = second();
Optional<String> result = tmp1.orElse(tmp2);
这里没有可选的特定内容-这就是参数求值始终在Java中工作的方式。
请注意,这是库构造(
orElse
)和条件运算符语言构造(?:
)之间的巨大区别,后者将仅计算第二个或第三个操作数,而不会同时计算这两个值。如Artur所述,如果要推迟对
second()
的调用,则需要使用orElseGet
,其中传递的参数不是first
没有一个值时要使用的值,而是为获得该参数而进行的调用值(value)。