为什么类型推断在 Java 中对 lambda 和方法引用的作用不同?
Why doesn't type inference work the same on lambdas and method references in Java?
代码不应该编译但它编译了!
public class MyClass {
...........
private void setEndDateOfValidStatusToCurrentTime(List<LifecycleStatus> oldStatuses, Date currentTime)
{
oldStatuses.stream()
.filter(oldStatus -> isValidNow(oldStatus, currentTime))
.findFirst().ifPresent(oldStatus -> oldStatus.setValidToDate(currentTime));
}
private boolean isValidNow(LifecycleStatus lifecycleStatus, Date currentTime)
{
Date start = lifecycleStatus.getValidFromDate();
Date end = lifecycleStatus.getValidToDate();
Date startTime = Optional.ofNullable(start).orElse(new Date(0L)); // BEGINNING OF TIME
Date endTime = Optional.ofNullable(end).orElse(new Date(Long.MAX_VALUE)); // END OF TIME
return startTime.before(currentTime) && endTime.after(currentTime);
}
}
原因:
我在 lambda 中使用 isValidNow() 来定位 Predicate 接口,因为过滤器方法需要它。但是 isValidNow() 是一个 2 参数方法,而 Predicate 中的 test() 只需要 1 个参数!
我知道 Java 编译器具有类型推断的能力。有了这样的能力,也许智能编译器会在内部分解 isValidNow(),确定它可以安全地搁置第二个参数 (currentTime),并通过仅使用第一个参数 (oldStatus) 来满足 Predicate 中的 test() 的实现.
那为什么当我尝试使用方法引用时类型推断不起作用?有趣的是,如果我替换
filter(oldStatus -> isValidNow(oldStatus, currentTime))
与
filter(this::isValidNow)
我看到这些编译器错误:
- The method filter(Predicate<? super LifecycleStatus>) in the type Stream<LifecycleStatus> is not applicable for the arguments
(this::isValidNow)
- MyClass does not define isValidNow(LifecycleStatus) that is applicable here
oldStatus -> isValidNow(oldStatus, currentTime)
就是这里的 predicate/lambda,并且只接受一个参数。该 lambda 实际上等同于:
new Predicate<LifecycleStatus> {
boolean test(LifecycleStatus oldStatus) {
return isValidNow(oldStatus, currentTime);
}
}
(其中 currentTime
是 local variable from the enclosing scope。)
这肯定与 this::isValidNow
不同,这就是后者无法编译的原因。
代码不应该编译但它编译了!
public class MyClass {
...........
private void setEndDateOfValidStatusToCurrentTime(List<LifecycleStatus> oldStatuses, Date currentTime)
{
oldStatuses.stream()
.filter(oldStatus -> isValidNow(oldStatus, currentTime))
.findFirst().ifPresent(oldStatus -> oldStatus.setValidToDate(currentTime));
}
private boolean isValidNow(LifecycleStatus lifecycleStatus, Date currentTime)
{
Date start = lifecycleStatus.getValidFromDate();
Date end = lifecycleStatus.getValidToDate();
Date startTime = Optional.ofNullable(start).orElse(new Date(0L)); // BEGINNING OF TIME
Date endTime = Optional.ofNullable(end).orElse(new Date(Long.MAX_VALUE)); // END OF TIME
return startTime.before(currentTime) && endTime.after(currentTime);
}
}
原因: 我在 lambda 中使用 isValidNow() 来定位 Predicate 接口,因为过滤器方法需要它。但是 isValidNow() 是一个 2 参数方法,而 Predicate 中的 test() 只需要 1 个参数!
我知道 Java 编译器具有类型推断的能力。有了这样的能力,也许智能编译器会在内部分解 isValidNow(),确定它可以安全地搁置第二个参数 (currentTime),并通过仅使用第一个参数 (oldStatus) 来满足 Predicate 中的 test() 的实现.
那为什么当我尝试使用方法引用时类型推断不起作用?有趣的是,如果我替换
filter(oldStatus -> isValidNow(oldStatus, currentTime))
与
filter(this::isValidNow)
我看到这些编译器错误:
- The method filter(Predicate<? super LifecycleStatus>) in the type Stream<LifecycleStatus> is not applicable for the arguments
(this::isValidNow)
- MyClass does not define isValidNow(LifecycleStatus) that is applicable here
oldStatus -> isValidNow(oldStatus, currentTime)
就是这里的 predicate/lambda,并且只接受一个参数。该 lambda 实际上等同于:
new Predicate<LifecycleStatus> {
boolean test(LifecycleStatus oldStatus) {
return isValidNow(oldStatus, currentTime);
}
}
(其中 currentTime
是 local variable from the enclosing scope。)
这肯定与 this::isValidNow
不同,这就是后者无法编译的原因。