java - 如何返回 lambda 函数并通过作为参数传递给 Java 8 中的方法来使用?为什么我不能使用 :: 运算符?
问题描述
我试图在我的 Role 类中实现自定义验证谓词。即isInRealm()
它返回一个Predicate<String>
并且是一个基本的,只是为了表明我的意图。
public enum Role {
USER("ROLE_user", 1),
CUSTOMER("ROLE_customer", 2),
//...
public static Predicate<String> isInRealm() {
return role -> Arrays.stream(values()).anyMatch(value -> value.value.equals(role));
}
}
我可以在客户端类中定义谓词,也可以直接作为 lambda 表达式或方法引用传递。(1)(2) 下面,有它们的案例,我已经注意到哪个有效或无效。
public class UserService {
//...
public User getUserProfile() {
//validateUser(Role.isInRealm()); -> OK
validateUser(Role::isInRealm); -> NOK
validateUser(r -> Role.isInRealm()); -> NOK
//validateUser(role -> Arrays.stream(Role.values()).anyMatch(value -> value.equals(role))); -> OK (1)
//validateUser(s -> true); -> OK (2)
//...
}
private void validateUser(Predicate<String> predicate) {
Authentication principal = SecurityContextHolder.getContext().getAuthentication();
String role = utils.getRoles(principal).findFirst().get().getAuthority();
if (!predicate.test(role)) {
throw new ForbiddenAccessException(ResponseCode.FORBIDDEN_ACCESS.getMessage());
}
}
}
我对如何获取Function
方法返回的句柄感到困惑。
虽然isInRealm()
方法将 lambda 表达式作为谓词返回,但为什么我不能用Role::isInRealm
or调用它r -> Role.isInRealm()
?当我尝试时,我得到bad return type in lambda expression: Predicate<String> cannot be converted to boolean
.
当我直接在客户端代码中传递 lambda 表达式时,它可以工作,但在这种情况下,我需要使用validateUser(Role.isInRealm())
. 为什么会这样?
Role.isInRealm()
这是有道理的,因为该方法返回一个函数对象,我们正在获取该对象,但由于 Java 8 流 API 函数不是一流的语言结构,我无法完全掌握使用::
.
当我们使用点或双冒号时,后面发生了什么?
解决方案
您将 lambda 与调用混合在一起。在以下示例isInRealm
中调用,并使用返回值 (lambda):
validateUser(Role.isInRealm());
所以有效地role -> Arrays.stream(values()).anyMatch(value -> value.value.equals(role));
传递给validateUser
方法。
在接下来的两个示例中:
validateUser(Role::isInRealm);
validateUser(r -> Role.isInRealm());
您正在尝试传递 lambdas(供应商),当被调用时将返回您正在寻找的 lambda。你没有传递Predicate
to validateUser
。
推荐阅读
- java - Spring boot 从 1.5.22 升级到 2.3.4,MvcEndpoint.class 有问题
- python - 出现错误:调用DeleteObject操作时发生错误(AccessDenied):从python删除文件/文件夹时访问被拒绝
- javascript - 本地存储无法在待办事项应用 REACT 中存储复选框
- python - VSCode Jupyter 加载不正确的 python 版本
- amazon-web-services - 如何避免从两个 lambda 覆盖 dynamodb?
- jenkins - Jenkins Pipeline 中是否有任何显示重建信息的环境变量?
- mysql - MySQL事务不回滚会有什么影响?
- php - Laravel 419 页面过期
- reactjs - react-dropdown-tree-select:是否可以将搜索区域向左移动?
- python - 将“轮廓”包包含到 matlplotlib 中并使用它设置标题