일반적인 인터페이스가 있다고 가정합니다.
interface MyComparable<T extends Comparable<T>> {
public int compare(T obj1, T obj2);
}
그리고 방법 sort
:
public static <T extends Comparable<T>>
void sort(List<T> list, MyComparable<T> comp) {
// sort the list
}
이 메서드를 호출하고 람다 식을 인수로 전달할 수 있습니다.
List<String> list = Arrays.asList("a", "b", "c");
sort(list, (a, b) -> a.compareTo(b));
잘 작동합니다.
그러나 이제 인터페이스를 제네릭이 아니고 메서드를 제네릭으로 만들면 다음과 같습니다.
interface MyComparable {
public <T extends Comparable<T>> int compare(T obj1, T obj2);
}
public static <T extends Comparable<T>>
void sort(List<T> list, MyComparable comp) {
}
그런 다음 다음과 같이 호출하십시오.
List<String> list = Arrays.asList("a", "b", "c");
sort(list, (a, b) -> a.compareTo(b));
컴파일되지 않습니다. 람다 식에서 다음과 같은 오류를 표시합니다.
“대상 방법이 일반적 임”
좋아,을 사용하여 컴파일하면 javac
다음 오류가 표시됩니다.
SO.java:20: error: incompatible types: cannot infer type-variable(s) T#1
sort(list, (a, b) -> a.compareTo(b));
^
(argument mismatch; invalid functional descriptor for lambda expression
method <T#2>(T#2,T#2)int in interface MyComparable is generic)
where T#1,T#2 are type-variables:
T#1 extends Comparable<T#1> declared in method <T#1>sort(List<T#1>,MyComparable)
T#2 extends Comparable<T#2> declared in method <T#2>compare(T#2,T#2)
1 error
이 오류 메시지에서 컴파일러가 유형 인수를 유추 할 수없는 것 같습니다. 그럴까요? 그렇다면 왜 이런 일이 발생합니까?
인터넷을 통해 다양한 방법으로 검색했습니다. 그런 다음 방법을 보여주는 이 JavaCodeGeeks 기사를 찾았 으므로 시도했습니다.
sort(list, <T extends Comparable<T>>(a, b) -> a.compareTo(b));
그 기사가 작동한다고 주장하는 것과는 달리 다시 작동하지 않습니다. 일부 초기 빌드에서 작동했을 가능성이 있습니다.
그래서 내 질문은 : 제네릭 메서드에 대한 람다 식을 만드는 방법이 있습니까? 메서드를 생성하여 메서드 참조를 사용하여이 작업을 수행 할 수 있습니다.
public static <T extends Comparable<T>> int compare(T obj1, T obj2) {
return obj1.compareTo(obj2);
}
어떤 수업에서는라고 말하고 다음 SO
과 같이 전달하십시오.
sort(list, SO::compare);
답변
당신은 사용할 수 없습니다 람다 식을 A에 대한 기능적인 인터페이스 의 방법 경우, 기능적인 인터페이스는 이 형식 매개 변수를 . JLS8의 섹션 §15.27.3을 참조하십시오 .
T 가 기능적 인터페이스 유형 (§9.8)이고 표현식이 [..] T의 함수 유형과 일치 하는 경우 람다 표현식은 대상 유형 T 와 호환 가능합니다 . [..] 람다 표현식은 합동입니다. 다음이 모두 참인 경우 함수 유형으로 :
- 함수 유형에는 유형 매개 변수 가 없습니다 .
- [..]
답변
메서드 참조를 사용하여 인수를 전달하는 다른 방법을 찾았습니다.
List<String> list = Arrays.asList("a", "b", "c");
sort(list, Comparable::<String>compareTo);
답변
컴파일러에게 적절한 버전의 일반 비교기를 지정하십시오.
(Comparator<String>)
그래서 대답은
sort(list, (Comparator<String>)(a, b) -> a.compareTo(b));
답변
당신은 다음과 같은 것을 의미합니까? :
<T,S>(T t, S s)->...
이 람다는 어떤 유형입니까? Java로 표현할 수 없으므로 함수 응용 프로그램에서이 표현식을 작성할 수 없으며 표현식을 구성 할 수 있어야합니다.
이 작업이 필요하려면 Java의 Rank2 유형 에 대한 지원이 필요합니다 .
메서드는 제네릭이 될 수 있지만 식으로 사용할 수 없습니다. 그러나 전달하기 전에 필요한 모든 제네릭 유형을 특수화하여 람다 표현식으로 줄일 수 있습니다.ClassName::<TypeName>methodName