如何比较java 8中的功能接口/方法引用

时间:2015-02-26 16:18:26

标签: java lambda java-8

是否可以执行以下操作:

boolean isItMyMethod( Consumer<Object> aConsumer )
{
    return aConsumer.equals( this::myMethod );
}

这不编译。如果我将此:: myMethod分配给中间变量,但结果始终为false。

1 个答案:

答案 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