The code should not compile but it does!
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);
}
}
Reason: I am using isValidNow() in a lambda in order to target the Predicate interface since the filter method requires it. But isValidNow() is a 2-argument method and test() in Predicate expects only 1 argument!
I do know the Java compiler has the power of type inference. With such power, perhaps the smart compiler internally breaks down isValidNow(), determines that it can safely put aside the second argument (currentTime) and come up with an implementation that satisfies test() in Predicate by using only the first argument (oldStatus).
Then why doesn't type inference work when I try to use a method reference instead? Interestingly, if I replace
filter(oldStatus -> isValidNow(oldStatus, currentTime))
with
filter(this::isValidNow)
I see these compiler errors:
- 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