为什么类型推断在Java中的lambdas和方法引用上不起作用?

时间:2017-11-16 19:45:11

标签: java lambda type-inference method-reference

代码不应该编译,但确实如此!

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接口,因为filter方法需要它。但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

1 个答案:

答案 0 :(得分:3)

oldStatus -> isValidNow(oldStatus, currentTime)是谓词/ lambda,只接受一个参数。 lambda实际上相当于:

new Predicate<LifecycleStatus> {
    boolean test(LifecycleStatus oldStatus) {
        return isValidNow(oldStatus, currentTime);
    }
}

(其中currentTimelocal variable from the enclosing scope。)

这肯定与this::isValidNow不一样,这就是后者无法编译的原因。