Supponiamo che io abbia un'interfaccia generica:
interface MyComparable<T extends Comparable<T>> {
public int compare(T obj1, T obj2);
}
E un metodo sort
:
public static <T extends Comparable<T>>
void sort(List<T> list, MyComparable<T> comp) {
// sort the list
}
Posso invocare questo metodo e passare un'espressione lambda come argomento:
List<String> list = Arrays.asList("a", "b", "c");
sort(list, (a, b) -> a.compareTo(b));
Funzionerà bene.
Ma ora se rendo l'interfaccia non generica e il metodo generico:
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) {
}
E poi invoca questo come:
List<String> list = Arrays.asList("a", "b", "c");
sort(list, (a, b) -> a.compareTo(b));
Non si compila. Mostra un errore nell'espressione lambda che dice:
"Il metodo di destinazione è generico"
OK, quando l'ho compilato usando javac
, mostra il seguente errore:
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
Da questo messaggio di errore, sembra che il compilatore non sia in grado di dedurre gli argomenti del tipo. È così? Se sì, allora perché sta succedendo in questo modo?
Ho provato vari modi, cercato su Internet. Poi ho trovato questo articolo JavaCodeGeeks , che mostra un modo, quindi ho provato:
sort(list, <T extends Comparable<T>>(a, b) -> a.compareTo(b));
che ancora una volta non funziona, contrariamente a quanto l'articolo afferma che funziona. Potrebbe essere possibile che funzionasse in alcune build iniziali.
Quindi la mia domanda è: esiste un modo per creare un'espressione lambda per un metodo generico? Posso farlo usando un metodo di riferimento, creando un metodo:
public static <T extends Comparable<T>> int compare(T obj1, T obj2) {
return obj1.compareTo(obj2);
}
in qualche classe dite SO
e passatelo come:
sort(list, SO::compare);