我在评估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";
}
Run Code Online (Sandbox Code Playgroud)
我的期望是,因为first()返回非空的Optional,所以不评估第二个.但事实上输出是:
Evaluating first
Evaluating second
GOT STRING: STRING OPTIONAL
Run Code Online (Sandbox Code Playgroud)
尝试在测试中使用orElse中使用的函数:
@Test
public void test2() {
System.out.println("GOT STRING: " + (first() != null ? "FIRST IS NOT NULL" : second()));
}
Run Code Online (Sandbox Code Playgroud)
输出:
Evaluating first
GOT STRING: FIRST IS NOT NULL
Run Code Online (Sandbox Code Playgroud)
为什么评估第二个选项?这似乎很糟糕?
Art*_*ski 10
它被评估,因为你传递的是值的second()值,而不是仅仅传递对函数本身的引用.您需要执行以下操作之一
System.out.println("GOT STRING: " + first().orElseGet(() ->second()));
System.out.println("GOT STRING: " + first().orElseGet(this::second));
Run Code Online (Sandbox Code Playgroud)
延迟评估直到真正需要.
为什么评估第二个选项?
因为您正在调用second()方法,以便将值作为参数提供orElse().参数的值将被忽略(因为您已经有了一个值),但这并不意味着它不必提供.
基本上,这段代码:
first().orElse(second())
Run Code Online (Sandbox Code Playgroud)
相当于:
Optional<String> tmp1 = first();
Optional<String> tmp2 = second();
Optional<String> result = tmp1.orElse(tmp2);
Run Code Online (Sandbox Code Playgroud)
这里没有任何特定的可选项 - 这就是参数评估在Java中始终有效的方式.
请注意,这是库构造(orElse)和条件运算符语言 construct(?:)之间的一个很大区别,它只会计算第二个或第三个操作数,但不会同时评估两者.
正如Artur所提到的,如果你想将调用推迟到second(),你需要使用orElseGet,你传递的参数不是要使用的值,如果first没有,那么调用make以获取值.