[java] Lambda 식 및 일반 메서드

일반적인 인터페이스가 있다고 가정합니다.

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


답변