orElseThrow 中的 lambda 表达式替代了什么?
what does the lambda expression in orElseThrow substitute?
让我们来看一些简单的示例代码:
Employee employee = repository.findById(id).orElseThrow(() -> new EmployeeNotFoundException(id));
根据我的理解,lambda 用于创建功能接口的子实例(只有 1 个方法),空括号表示该方法没有参数。
但是需要lambda的orElseThrow调用了什么方法呢?我认为它是 Optional
或 Exception
。
所以我的问题是:如果没有 lambda 调用,这会是什么样子?
员工class:
class Employee {
private Long id;
private String name;
private String role;
Employee() {}
Employee(String name, String role) {
this.name = name;
this.role = role;
}
}
和异常 class:
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 时情况并非如此。这表明我不知道如何实现供应商 class 手动而不是通过使用 lambdas
跳过所有这些
通过查看 Optional 的 JavaDoc 可以很容易地回答这个问题:
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}
lambda 参数是提供要抛出的异常的供应商。
Optional::orElseThrow
takes a Supplier
并且此 Supplier
用于获取 Exception
的实例,如果 Optional
下面具有 null
值,则将抛出该实例。查看 Optional::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();
}
}
它只是检查值是否存在,如果不存在 - 它从 Supplier
获取 Execption 实例并抛出它。
表达式:
() -> new EmployeeNotFoundException(id)
符合 Optional::orElseThrow
方法预期的 Supplier
- Supplier<? extends X> exceptionSupplier
其中 X
扩展 Throwable
。它甚至可以被提取到单独的变量中:
Supplier<EmployeeNotFoundException> execptionSupplier = () -> new EmployeeNotFoundException(id);
Employee employee = repository.findById(id).orElseThrow(execptionSupplier);
orElseThrow
是 Optional
class 的一种方法,具有以下签名:
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X
这意味着您传递的 lambda 表达式必须符合 Supplier<? extends X>
函数接口。 Supplier<T>
功能接口有一个不接受任何参数的方法和 returns T
的一个实例:T get()
.
您的 lambda 表达式 - () -> new EmployeeNotFoundException(id)
- 匹配此功能接口。
此功能接口的 get()
方法用于创建 Throwable
实例,当 Optional
为空时 orElseThrow()
将抛出该实例。
我没有测试过,但我相信为了避免处理一般的 Throwable
(通过在你的方法签名中声明它或在你的封闭方法中捕获它)你需要提供一个 Supplier<RuntimeException>
或类似的比 RuntimeException
更具体的类型。例如:
Employee employee = repository.findById(id).orElseThrow(
new Supplier<EmployeeNotFoundException>() {
@Override
public EmployeeNotFoundException get() {
return new EmployeeNotFoundException(id);
}
}
);
由于 EmployeeNotFoundException
是一个 RuntimeException
,因此是一个未经检查的异常,编译器不会关心你是否处理异常。
您已经正确阅读了文档,至少部分正确:我们传递给 orElseThrow
的是一个 Supplier
,所以这是 lambda 实现的接口,也是我们需要实现的接口无论我们是传递一个方法引用、一个 lambda 还是像您的情况那样传递一个用 new
实例化的对象。 Supplier
是采用一种类型参数的通用接口。文档还告诉我们 orElseThrow
需要 Supplier<? extends X>
,其中 X extends Throwable
,即 X
是 Throwable
的子类型。所以传递 Supplier<Throwable>
并没有错,但是正如你所经历的,它给你带来了一些麻烦。我们被允许放入 Throwable
的任何子类型。输入 RuntimeException
或 EmployeeNotFoundException
可以让我们摆脱麻烦。
不过,当 lambda 运行良好时,我不知道你为什么要这么罗嗦。
让我们来看一些简单的示例代码:
Employee employee = repository.findById(id).orElseThrow(() -> new EmployeeNotFoundException(id));
根据我的理解,lambda 用于创建功能接口的子实例(只有 1 个方法),空括号表示该方法没有参数。
但是需要lambda的orElseThrow调用了什么方法呢?我认为它是 Optional
或 Exception
。
所以我的问题是:如果没有 lambda 调用,这会是什么样子?
员工class:
class Employee {
private Long id;
private String name;
private String role;
Employee() {}
Employee(String name, String role) {
this.name = name;
this.role = role;
}
}
和异常 class:
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 时情况并非如此。这表明我不知道如何实现供应商 class 手动而不是通过使用 lambdas
跳过所有这些通过查看 Optional 的 JavaDoc 可以很容易地回答这个问题:
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}
lambda 参数是提供要抛出的异常的供应商。
Optional::orElseThrow
takes a Supplier
并且此 Supplier
用于获取 Exception
的实例,如果 Optional
下面具有 null
值,则将抛出该实例。查看 Optional::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();
}
}
它只是检查值是否存在,如果不存在 - 它从 Supplier
获取 Execption 实例并抛出它。
表达式:
() -> new EmployeeNotFoundException(id)
符合 Optional::orElseThrow
方法预期的 Supplier
- Supplier<? extends X> exceptionSupplier
其中 X
扩展 Throwable
。它甚至可以被提取到单独的变量中:
Supplier<EmployeeNotFoundException> execptionSupplier = () -> new EmployeeNotFoundException(id);
Employee employee = repository.findById(id).orElseThrow(execptionSupplier);
orElseThrow
是 Optional
class 的一种方法,具有以下签名:
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X
这意味着您传递的 lambda 表达式必须符合 Supplier<? extends X>
函数接口。 Supplier<T>
功能接口有一个不接受任何参数的方法和 returns T
的一个实例:T get()
.
您的 lambda 表达式 - () -> new EmployeeNotFoundException(id)
- 匹配此功能接口。
此功能接口的 get()
方法用于创建 Throwable
实例,当 Optional
为空时 orElseThrow()
将抛出该实例。
我没有测试过,但我相信为了避免处理一般的 Throwable
(通过在你的方法签名中声明它或在你的封闭方法中捕获它)你需要提供一个 Supplier<RuntimeException>
或类似的比 RuntimeException
更具体的类型。例如:
Employee employee = repository.findById(id).orElseThrow(
new Supplier<EmployeeNotFoundException>() {
@Override
public EmployeeNotFoundException get() {
return new EmployeeNotFoundException(id);
}
}
);
由于 EmployeeNotFoundException
是一个 RuntimeException
,因此是一个未经检查的异常,编译器不会关心你是否处理异常。
您已经正确阅读了文档,至少部分正确:我们传递给 orElseThrow
的是一个 Supplier
,所以这是 lambda 实现的接口,也是我们需要实现的接口无论我们是传递一个方法引用、一个 lambda 还是像您的情况那样传递一个用 new
实例化的对象。 Supplier
是采用一种类型参数的通用接口。文档还告诉我们 orElseThrow
需要 Supplier<? extends X>
,其中 X extends Throwable
,即 X
是 Throwable
的子类型。所以传递 Supplier<Throwable>
并没有错,但是正如你所经历的,它给你带来了一些麻烦。我们被允许放入 Throwable
的任何子类型。输入 RuntimeException
或 EmployeeNotFoundException
可以让我们摆脱麻烦。
不过,当 lambda 运行良好时,我不知道你为什么要这么罗嗦。