为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕桂英546537 2023-09-20 14:50:51
让我们看一些简单的示例代码: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 跳过所有这些
查看完整描述

4 回答

?
陪伴而非守候

TA贡献1757条经验 获得超8个赞

通过查看可选的 JavaDoc,可以很容易地回答这个问题:


public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {

    if (value != null) {

        return value;

    } else {

        throw exceptionSupplier.get();

    }

}

lambda 参数是提供要抛出的异常的提供者。


查看完整回答
反对 回复 2023-09-20
?
交互式爱情

TA贡献1712条经验 获得超3个赞

orElseThrowOptional是具有以下签名的类的方法:

public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X

这意味着您传递的 lambda 表达式必须符合Supplier<? extends X>函数接口。函数式接口有一个方法,不接受参数并返回:Supplier<T>的实例。TT get()

您的 lambda 表达式 - () -> new EmployeeNotFoundException(id)- 与此函数式接口匹配。

该函数接口的get()方法用于创建当 为空时将抛出Throwable的实例。orElseThrow()Optional


查看完整回答
反对 回复 2023-09-20
?
料青山看我应如是

TA贡献1772条经验 获得超7个赞

我还没有测试过,但我相信,为了避免必须处理一般性Throwable(通过在方法签名中声明它或在封闭方法中捕获它),您需要提供 aSupplier<RuntimeException>或类似的比RuntimeException. 例如:


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

        new Supplier<EmployeeNotFoundException>() {

            @Override

            public EmployeeNotFoundException get() {

                return new EmployeeNotFoundException(id);

            }

        }

    );

由于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 工作正常时,我不知道为什么你要这么啰嗦。


查看完整回答
反对 回复 2023-09-20
?
收到一只叮咚

TA贡献1821条经验 获得超4个赞

Optional::orElseThrow接受 a Supplier,这Supplier用于获取一个实例,如果该实例具有下面的值Exception,则该实例将被抛出。请参阅实现:OptionalnullOptional::orElseThrow


public <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> exceptionSupplierXThrowable


Supplier<EmployeeNotFoundException> execptionSupplier = () -> new EmployeeNotFoundException(id);

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


查看完整回答
反对 回复 2023-09-20
  • 4 回答
  • 0 关注
  • 89 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信