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);