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
ObjectcontainingObject::instanceMethodName
的特定对象的实例方法- 引用特定类型
ContainingType::methodName
的任意对象的实例方法- 引用构造函数
ClassName::new
所以你看,方法引用不仅限于static
方法。
您的方法引用Comparable::
匹配“对特定类型的任意对象的实例方法的引用”的类型。
此时值得注意的是,您实际上是在引用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()
( String
, String
)的参数列表可以与String#compareTo()
( this
, String
)的参数列表匹配,它们的返回类型也相同( int
),因此可以用作lambda当另一个人被期待。