Java Lambda表达式

我目前正在JDK 1.8上学习lambda表达式。 我遇到了一些我发现我不明白的代码。

这是代码:

import java.util.Arrays; import java.util.Comparator; import java.util.List; import java.lang.Comparable; /** * Hello world! * */ public class App { public static void main( String[] args ) throws Exception { List list = Arrays.asList("a", "b", "c"); sort(list, Comparable::compareTo); } interface MyComparable { public <T extends Comparable> int compare(T obj1, T obj2 ); } public static <T extends Comparable> void sort(List list, MyComparable comp) { int n = comp.compare("5","2"); System.out.println(n); } } 

comp.compare("5", "3")最终执行"5".compareTo("2") 。 我的理解是编译器需要找到一个具有相同签名的静态方法

 public <T extends Comparable> int compare(T obj1, T obj2 ); 

我创建了这样一个方法,它的工作原理。 我不明白为什么java编译器调用"5".compareTo("2") 。 他们的方法标志不一样。

有关编译器为何生成此类代码的任何信息?

如果您正在尝试学习方法参考,您应该使用某种学习材料,例如Oracle的Java教程 。 在那里你会发现:

各种方法参考

亲切的例子

  • 引用静态方法ContainingClass::staticMethodName
  • 引用containingObject::instanceMethodName Object containingObject::instanceMethodName的特定对象的实例方法
  • 引用特定类型ContainingType::methodName的任意对象的实例方法
  • 引用构造函数ClassName::new

所以你看,方法引用不仅限于static方法。

您的方法引用Comparable::compareTo匹配“对特定类型的任意对象的实例方法的引用”的类型。

此时值得注意的是,您实际上是在引用Comparable.compareTo方法,就像您编写了Comparable::compareTo 。 由于引用的方法本身没有类型参数,因此类型参数无效。 例如,您可以使用相同的结果编写Comparable::

引用的方法具有函数签名(Comparable,Comparable) → int因为它在一个Comparable上调用Comparable.compareTo时消耗两个Comparable ,将第二个Comparable作为参数传递(并且它将返回一个int )。 这与您的interface的function签名相匹配

 interface MyComparable { public > int compare(T obj1, T obj2 ); } 

所以方法参考可以在这种情况下使用。

我简化了function签名; 实际上它们是(T,T)→int使用> ,因此您只能使用此函数Comparable 同一具体Comparable实现的两个实例。

所以你想知道具有不同于预期的签名的方法引用如何作为lambda表达式发送。 但它们不需要完全相同。 基本上,只有参数列表返回类型很重要:

如果满足以下所有条件,则可以将lambda表达式分配给目标类型T.

  • T是function接口类型

  • lambda表达式与T的方法具有相同数量的参数,并且这些参数的类型是相同的

  • lambda主体返回的每个表达式都与T的方法的返回类型兼容

  • T的方法的throws子句允许lambda体抛出的每个exception

从这里(第4节)

compare()StringString )的参数列表可以与String#compareTo()thisString )的参数列表匹配,它们的返回类型也相同( int ),因此可以用作lambda当另一个人被期待。