일부 사용자 개체가있는 목록이 있고 목록을 정렬하려고하지만 메서드 참조를 사용하여 작동하며 람다 식을 사용하면 컴파일러에서 오류가 발생합니다.
List<User> userList = Arrays.asList(u1, u2, u3);
userList.sort(Comparator.comparing(u -> u.getName())); // works
userList.sort(Comparator.comparing(User::getName).reversed()); // works
userList.sort(Comparator.comparing(u -> u.getName()).reversed()); // Compiler error
오류:
com\java8\collectionapi\CollectionTest.java:35: error: cannot find symbol
userList.sort(Comparator.comparing(u -> u.getName()).reversed());
^
symbol: method getName()
location: variable u of type Object
1 error
답변
이것은 컴파일러의 유형 추론 메커니즘의 약점입니다. u
람다 의 유형을 추론하려면 람다의 대상 유형 을 설정해야합니다. 이것은 다음과 같이 수행됩니다. userList.sort()
유형의 인수가 필요합니다 Comparator<User>
. 첫 번째 줄에서 Comparator.comparing()
를 반환해야합니다 Comparator<User>
. 이것은 그 의미 Comparator.comparing()
필요 Function
소요 User
인수를. 따라서 첫 번째 줄의 람다에서 u
유형이어야 User
하며 모든 것이 작동합니다.
두 번째 및 세 번째 줄에서에 대한 호출의 존재로 인해 대상 입력이 중단됩니다 reversed()
. 나는 그 이유를 완전히 모르겠습니다. 수신자와 반환 유형이 reversed()
모두 Comparator<T>
있으므로 대상 유형이 수신자에게 다시 전파되어야하는 것처럼 보이지만 그렇지 않습니다. (내가 말했듯이 약점이다.)
두 번째 줄에서 메서드 참조는이 간격을 채우는 추가 유형 정보를 제공합니다. 컴파일러를 추론이 때문에이 정보는, 세 번째 줄에서 부재 u
로 Object
실패 (최후의 추론 대체).
분명히 메서드 참조를 사용할 수 있다면 그렇게하면 작동합니다. 예를 들어 추가 매개 변수를 전달하려는 경우와 같이 메서드 참조를 사용할 수없는 경우가 있으므로 람다 식을 사용해야합니다. 이 경우 람다에 명시 적 매개 변수 유형을 제공합니다.
userList.sort(Comparator.comparing((User u) -> u.getName()).reversed());
향후 릴리스에서이 경우를 다루기 위해 컴파일러를 향상시킬 수 있습니다.
답변
두 번째 인수로 Comparator.comparing
with 두 인수 를 사용하여이 제한을 해결할 수 있습니다 Comparator.reverseOrder()
.
users.sort(comparing(User::getName, reverseOrder()));