猿问

orElseThrow 中的 lambda 表达式替换了什么?

让我们看一些简单的示例代码:


Employee employee = repository.findById(id).orElseThrow(() -> new EmployeeNotFoundException(id));

根据我的理解,lambda用于创建函数式接口的替代(只有1个方法),空括号意味着该方法没有参数。


但是 orElseThrow 中调用了什么方法需要 lambda 呢?我认为它要么是一个Optional,要么是一个Exception。


所以我的问题是:如果没有 lambda 调用,这会是什么样子?


员工类别:


class Employee {


    private Long id;

    private String name;

    private String role;


    Employee() {}


    Employee(String name, String role) {

        this.name = name;

        this.role = role;

    }

}

和异常类:


class EmployeeNotFoundException extends RuntimeException {


    EmployeeNotFoundException(Long id) {

        super("Could not find employee " + id);

    }

}

编辑:我对如何为 lambda 表达式编写有效的、可编译的替换感兴趣。现在我在


        Employee employee = repository.findById(id).orElseThrow(

            new Supplier<Throwable>() {

                @Override

                public Throwable get() {

                    return new EmployeeNotFoundException(id);

                }

            }

        )

但这是不对的,因为现在我需要将异常添加到方法签名中,而使用 lambda 时情况并非如此。它表明我不知道如何手动实现供应商类,而不仅仅是使用 lambda 跳过所有这些


慕桂英546537
浏览 148回答 4
4回答

陪伴而非守候

通过查看可选的 JavaDoc,可以很容易地回答这个问题:public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {&nbsp; &nbsp; if (value != null) {&nbsp; &nbsp; &nbsp; &nbsp; return value;&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; throw exceptionSupplier.get();&nbsp; &nbsp; }}lambda 参数是提供要抛出的异常的提供者。

交互式爱情

orElseThrowOptional是具有以下签名的类的方法:public&nbsp;<X&nbsp;extends&nbsp;Throwable>&nbsp;T&nbsp;orElseThrow(Supplier<?&nbsp;extends&nbsp;X>&nbsp;exceptionSupplier)&nbsp;throws&nbsp;X这意味着您传递的 lambda 表达式必须符合Supplier<? extends X>函数接口。函数式接口有一个方法,不接受参数并返回:Supplier<T>的实例。TT get()您的 lambda 表达式 -&nbsp;() -> new EmployeeNotFoundException(id)- 与此函数式接口匹配。该函数接口的get()方法用于创建当 为空时将抛出Throwable的实例。orElseThrow()Optional

料青山看我应如是

我还没有测试过,但我相信,为了避免必须处理一般性Throwable(通过在方法签名中声明它或在封闭方法中捕获它),您需要提供 aSupplier<RuntimeException>或类似的比RuntimeException. 例如:&nbsp; &nbsp; Employee employee = repository.findById(id).orElseThrow(&nbsp; &nbsp; &nbsp; &nbsp; new Supplier<EmployeeNotFoundException>() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; public EmployeeNotFoundException get() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return new EmployeeNotFoundException(id);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; );由于EmployeeNotFoundException是一个RuntimeException未经检查的异常,因此编译器不会关心您是否处理异常。您已经正确阅读了文档,至少部分正确:我们传递给的orElseThrow是 a Supplier,所以这是 lambda 实现的接口,也是我们需要实现的接口,无论我们传递方法引用、lambda 还是像您中那样case,一个用 实例化的对象new。Supplier是一个采用一种类型参数的通用接口。该文档还告诉我们orElseThrow需要一个Supplier<? extends X>where X extends Throwable,即X是 的子类型Throwable。所以传递 aSupplier<Throwable>并不是不正确的,但正如你所经历的,它在其他地方给你带来了一些麻烦。我们可以输入任何子类型Throwable来代替。输入RuntimeExceptionor 可以EmployeeNotFoundException让我们摆脱麻烦。不过,当 lambda 工作正常时,我不知道为什么你要这么啰嗦。

收到一只叮咚

Optional::orElseThrow接受 a Supplier,这Supplier用于获取一个实例,如果该实例具有下面的值Exception,则该实例将被抛出。请参阅实现:OptionalnullOptional::orElseThrowpublic <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {    if (this.value != null) {        return this.value;    } else {        throw (Throwable)exceptionSupplier.get();    }}它只是检查值是否存在,如果不存在,它会从中获取 Execption 实例Supplier并抛出它。和表达:() -> new EmployeeNotFoundException(id)符合方法 - where extendsSupplier的预期。它甚至可以被提取为单独的变量:Optional::orElseThrowSupplier<? extends X> exceptionSupplierXThrowableSupplier<EmployeeNotFoundException> execptionSupplier = () -> new EmployeeNotFoundException(id);Employee employee = repository.findById(id).orElseThrow(execptionSupplier);
随时随地看视频慕课网APP

相关分类

Java
我要回答