สมมติว่าฉันมีอินเทอร์เฟซทั่วไป:
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);