我对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)。

10-08 01:19