【问题标题】:Java8 -Optional.orElseGet with Supplier defined inside () vs in method callJava8 -Optional.orElseGet 在 () 与方法调用中定义了供应商
【发布时间】:2021-07-28 17:58:21
【问题描述】:

根据文档的区别

orElse 和 orElseGet 在 orElseGet(x) 的情况下是 x 部分

在 Optional.isPresent 为 false 时调用

但在下面的程序中,如果供应商 x 是 orElseGet(x) 中的另一个方法调用

即使 Optional.isPresent 是 true ,也会调用 x 部分,类似于

orElse()。为什么 orElseGet() 在这种情况下的行为与 orElse() 相同?

import java.util.Optional;
import java.util.function.Supplier;

public class TestOrElseGet {

    public static void main(String[] args) {
         
        checkOrElseGet();
    }

    private static void checkOrElseGet() {
        System.out.println("------Start Optional.orElseGet-------");

        String first= getFirst();

        //  else part is not initialized 

        // else  doesn't get initialized if its inside OrElseGet()
        String  myOptional = Optional.of(first).orElseGet(() -> {
            System.out.println("OrElseGet - Create & Return Second");            
            return "Second";
        });

        System.out.println(
                "Result of OrElseGet  " + myOptional);

        //  if supplier is a method then its gets called 

        myOptional = Optional.of(getThird()).orElseGet(getNumberFromSupplier());

        System.out.println(" Result of OrElseGet is "
                + myOptional);
 
        

        Optional<String> empty = Optional.empty();
        // OrElseGet - else is initialized as optional was empty
        myOptional = empty.orElseGet(() -> {
            System.out.println("OrElseGet - Create & Return Fourth"); 
            return "Four" ;
        });

        System.out.println("Result of OrElseGEt is " + myOptional);

        System.out.println("----------Completed-----------");
    }

    private static Supplier<String> getNumberFromSupplier() {
        System.out.println("Inside Supplier call..");
        return ()->{ 
            return "Supplying TEN";
        };
    }

    private static String getThird() {
        System.out.println("Inside Third");
        return "Third";
    }

    private static String getFirst() {
        System.out.println("Inside GetFirst");
        return "First";
    }
}

【问题讨论】:

    标签: java-8 optional


    【解决方案1】:

    orElseGet(Supplier) 的合约规定 →Supplier← 只有在值不存在时才会被调用。更具体地说,延迟调用的是 Supplier#get() 方法(在传递给 orElseGetSupplier 实例上)。

    您的代码显示了这一点。但是,这一点:

    private static Supplier<String> getNumberFromSupplier() {
        System.out.println("Inside Supplier call..");
        return ()->{ 
            return "Supplying TEN";
        };
    }
    

    表示误解。您的println 日志显示“内部供应商呼叫...”,但此时您不在供应商内部Supplier 是 lambda 表达式,由方法返回。也就是说,您是正确的 getNumberFromSupplier 方法被急切地调用,但这是因为它的返回值作为参数传递给 orElseGet 调用。即使对于orElseGet(() -&gt; ... )Supplier 也是出于同样的原因急切地创建。

    如果您有以下情况:

    private static Supplier<String> getNumberFromSupplier() {
        // Remember, the lambda is the implementation of Supplier#get()
        return () -> {
            System.out.println("Inside Supplier call...");
            return "Supplying TEN";
        };
    }
    

    然后您会看到 Supplier 被延迟调用。注意println 呼叫的新位置。此外,将该方法命名为getNumberSupplier 会更好,因为这样更贴切地描述了该方法的实际作用。

    【讨论】:

    • 感谢 Slaw 的详细解答,澄清了疑惑。
    猜你喜欢
    • 2018-10-14
    • 1970-01-01
    • 2019-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-02
    相关资源
    最近更新 更多