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

How to compare functional interfaces / method references in java 8

是否可以这样做:

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

这不编译。如果我将 this::myMethod 分配给一个中间变量,它会这样做,但结果总是错误的。

方法引用或 lambda 的目标类型应该是功能接口。由于 equals() 方法接受一个 Object,它不是函数式接口,因此无法编译。现在你会说,为什么?好吧,lambda 表达式或方法引用在运行时被实现为实现该功能接口的 class 的实例。 FI 仅包含一个抽象方法,因此对于 lambda x -> Sysout(x),左侧部分成为该方法的参数,右侧部分成为主体。

现在可以有很多功能接口,提供这样的方法签名。这意味着可以将相同的 lambda 表达式编译为不同 FI 的实现。现在,当你像这样将 lambda 传递给 Object 引用时:

Object ob = x -> Sysout(x);

您希望 JVM 实例化哪个 FI?这会导致一定的歧义,因此是不允许的。但是通过将 lambda 预分配给 FI 引用:

Consumer<Object> consumer = x -> Sysout(x);

您已经为 lambda 指定了一个具体的含义,之后可以将其指定给它的任何超类型引用。

Object ob = consumer;

现在至于为什么equals()方法return是false,大家可以猜到。由于 lambda 是在运行时构造的 class 的实例,它将提供 FI 中抽象方法的实现,您希望在什么基础上比较两个 Consumer 引用?由于没有覆盖 equals() 方法,它将调用 Object class 中的实现,它只是比较引用。实现看起来像这样:

public boolean equals(Object ob) {
    return this == ob;
}

当然 aConsumer == bConsumer 会 return false,如果两者都引用 2 个不同的 lambdas / 方法引用。