Lambdaexpression式和通用方法
假设我有一个通用的接口:
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 }
我可以调用这个方法,并传递一个lambdaexpression式作为参数:
List<String> list = Arrays.asList("a", "b", "c"); sort(list, (a, b) -> a.compareTo(b));
这将工作正常。
但是现在如果我使接口非generics,并且generics的方法:
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));
它不编译。 它显示lambdaexpression式的错误说:
“目标方法是通用的”
好的,当我使用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
从这个错误信息看来,编译器似乎无法推断types参数。 是这样吗? 如果是,那为什么会这样呢?
我尝试了各种方式,通过互联网search。 然后,我发现这个JavaCodeGeeks文章 ,这显示了一种方式,所以我试过:
sort(list, <T extends Comparable<T>>(a, b) -> a.compareTo(b));
这再次不起作用,这与该文称其有效。 可能有可能它曾经在一些最初的版本中工作。
所以我的问题是:有什么办法来创build一个generics方法的lambdaexpression式? 我可以通过创build一个方法使用方法引用来完成此操作:
public static <T extends Comparable<T>> int compare(T obj1, T obj2) { return obj1.compareTo(obj2); }
在某些课堂上说,这样做,并通过它:
sort(list, SO::compare);
如果function接口中的方法具有types参数 ,则不能将lambdaexpression式用于function接口 。 请参阅JLS8中的第15.27.3节 :
如果T是一个函数接口types(§9.8),并且该expression式与[..] T的函数types一致 ,则lambdaexpression式与目标typesT是兼容的.. [..] lambdaexpression式是一致的如果以下所有条件都成立,则使用函数types:
- 函数types没有types参数 。
- [..]
使用方法引用,我发现了另一种方式来传递参数:
List<String> list = Arrays.asList("a", "b", "c"); sort(list, Comparable::<String>compareTo);