这里是代码片段,它在 java 8 中的第 2 行抛出了有线编译错误。
List<Employee> employees = getEmployees();
/*Line no:2*/ Comparator<String> comparator = ((emp1, emp2) -> emp1.compareTo(emp2)).reversed(); // ERROR The target type of this expression must be a functional interface
return employees.stream().map(emp -> emp.getName()).sorted(comparator)
.collect(Collectors.toList());
但是相同的代码在第 3 行正确编译和运行
List<Employee> employees = getEmployees();
Comparator<String> comparator = ((emp1, emp2) -> emp1.compareTo(emp2));
/* Line no:3 */ comparator = comparator.reversed(); // NO ERROR GENERATED
return employees.stream().map(emp -> emp.getName()).sorted(comparator)
.collect(Collectors.toList());
有人可以向我解释幕后发生的事情以及为什么会出现此错误吗?
lambda 只是一种更简洁的方式来生成功能接口的实现。它只能在清楚 lambda 应该符合什么类型的情况下使用。在表达式
((emp1, emp2) -> emp1.compareTo(emp2)).reversed()
的上下文中,lambda 不会立即被分配给变量或传递给函数(这将允许推断其类型),而是更大表达式的子表达式。这导致了问题。
您可以通过强制转换使类型显式:
var comparator = ((Comparator<String>)(emp1, emp2) -> emp1.compareTo(emp2)).reversed();
来自Java教程:
为了确定 lambda 表达式的类型,Java 编译器使用找到 lambda 表达式的上下文或情况的目标类型。因此,您只能在 Java 编译器可以确定目标类型的情况下使用 lambda 表达式:
- 变量声明
- 作业
- 退货单
- 数组初始化器
- 方法或构造函数参数
- Lambda 表达式体
- 条件表达式,
?:
- 演员表