是否可以执行以下操作:
boolean isItMyMethod( Consumer<Object> aConsumer )
{
return aConsumer.equals( this::myMethod );
}
这不编译。如果我将此:: myMethod分配给中间变量,但结果始终为false。
答案 0 :(得分:3)
方法引用的目标类型或lambda应该是一个功能接口。由于equals()
方法采用Object
,这不是一个功能接口,因此无法编译。现在你会说,为什么?嗯,lambda表达式或方法引用在运行时实现为实现该功能接口的类的实例。 FI仅包含一个抽象方法,因此对于lambda x -> Sysout(x)
,左边部分成为该方法的参数,右边部分成为body。
现在可以有很多功能界面,提供这样的方法签名。这意味着可以将相同的lambda表达式编译为不同FI的实现。现在,当你将lambda传递给Object
这样的引用时:
Object ob = x -> Sysout(x);
你希望JVM实例化哪个FI?这导致某些歧义,因此是不允许的。但是通过预先将lambda分配给FI参考:
Consumer<Object> consumer = x -> Sysout(x);
你已经为lambda分配了一个具体的含义,然后可以将其分配给它的任何超类型引用。
Object ob = consumer;
现在,为什么equals()
方法返回false
,你可以猜到它。由于lambda是在运行时构造的类的实例,它将在FI中提供抽象方法的实现,在什么基础上你想要两个Consumer
引用进行比较?由于没有覆盖equals()
方法,它将调用Object
类中的实现,该类仅比较引用。实现如下:
public boolean equals(Object ob) {
return this == ob;
}
如果两者都指的是2个不同的lambda /方法引用,那么aConsumer == bConsumer
肯定会返回false
。