2017-11-16 19 views
0

코드가 컴파일되지 않아야하지만!lambda와 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); 
    } 

} 

이유 : 필터 방법을 필요 때문에 술어 인터페이스를 타겟팅하기 위하여 I는 람다 isValidNow()를 사용하고 . 그러나 isValidNow()는 2 인자의 메소드이고 Predicate의 test()는 오직 1 인자만을 요구합니다!

Java 컴파일러에는 형식 유추가 있습니다. 이러한 힘으로 스마트 컴파일러는 내부적으로 isValidNow()를 중단하고 두 번째 인수 (currentTime)를 안전하게 제 위치에두고 첫 번째 인수 (oldStatus) 만 사용하여 Predicate에서 test()를 충족시키는 구현을 결정할 수 있습니다. .

그렇다면 대신 메써드 참조를 사용하려고 할 때 유추가 작동하지 않는 이유는 무엇입니까? 흥미롭게도, 나는 내가

filter(this::isValidNow) 

이러한 컴파일러 오류를

filter(oldStatus -> isValidNow(oldStatus, currentTime)) 

를 참조 대체 할 경우 :

- 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 

답변

3

oldStatus -> isValidNow(oldStatus, currentTime) 여기 술어/람다, 그리고 단 하나 개의 인수를합니다.

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

후자 컴파일되지 않는 이유이다 확실히 this::isValidNow 같은 아니다

(currentTimelocal variable from the enclosing scope 곳이다.) 즉, λ는 효과적으로 등가이다.

+0

람다 식의 오른쪽에 하나의 인수 술어 메서드 테스트 (T t)를 따르기 위해, 원하는만큼 많은 인수를 가진 메서드를 사용할 수 있습니다. 옆에는 단 하나 뿐인가? – softwarelover

+0

@softwarelover - lambda는 (이 경우) 하나의 인수와 표현식 간의 매핑입니다. 그 표현은 당신이 원하는 어떤 것이라도 될 수 있습니다. –

+0

oldStatus가 인수로 전달되는 포지티브 구현에 대한 해당 코드에서 볼 수 있습니다. currentTime은 어떨까요? test() 메서드는 isValidNow()를 호출하지만 test()는 currentTime을 어떻게 알 수 있습니까? 나는 currentTime의 선언을 보지 못했다. 명확히하십시오. – softwarelover