<分区>
是否可以这样做:
boolean isItMyMethod( Consumer<Object> aConsumer )
{
return aConsumer.equals( this::myMethod );
}
这不会编译。如果我将 this::myMethod 分配给中间变量,它会执行此操作,但结果始终为 false。
<分区>
是否可以这样做:
boolean isItMyMethod( Consumer<Object> aConsumer )
{
return aConsumer.equals( this::myMethod );
}
这不会编译。如果我将 this::myMethod 分配给中间变量,它会执行此操作,但结果始终为 false。
最佳答案
方法引用或 lambda 的目标类型应该是函数式接口(interface)。由于 equals()
方法接受一个 Object
,它不是函数式接口(interface),因此无法编译。现在你会说,为什么?好吧,lambda 表达式或方法引用在运行时被实现为实现该功能接口(interface)的类的实例。 FI 仅包含一个抽象方法,因此对于 lambda x -> Sysout(x)
,左侧部分成为该方法的参数,右侧部分成为主体。
现在可以有很多功能接口(interface),提供这样的方法签名。这意味着可以将相同的 lambda 表达式编译为不同 FI 的实现。现在,当您像这样将 lambda 传递给 Object
引用时:
Object ob = x -> Sysout(x);
您希望 JVM 实例化哪个 FI?这会导致一定的歧义,因此是不允许的。但是通过将 lambda 预分配给 FI 引用:
Consumer<Object> consumer = x -> Sysout(x);
您已经为 lambda 赋予了具体的含义,之后可以将其赋予它的任何父类(super class)型引用。
Object ob = consumer;
现在至于为什么equals()
方法返回false
,你可以猜到。由于 lambda 是在运行时构造的类的实例,它将提供 FI 中抽象方法的实现,您希望在什么基础上比较两个 Consumer
引用?由于没有重写 equals()
方法,它将调用 Object
类中的实现,它只是比较引用。实现看起来像这样:
public boolean equals(Object ob) {
return this == ob;
}
当然 aConsumer == bConsumer
将返回 false
,如果两者都引用 2 个不同的 lambdas/方法引用。
关于java - 如何比较 java 8 中的功能接口(interface)/方法引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28747433/
相关文章:
java - 为什么 Java-8 lambda 需要 invokeDynamic byteCode 来调用接口(interface)方法
java - 为什么 Collections.sort(List) 在 Java 8 中使用 CopyOnWriteArrayList 而在 Java 7 中不起作用?
java - 如何通过远程接口(interface)使用@EJB”
java - 从 java.util.function.Function 获取方法名称
c++ - 使用 gcc 捕获 lambda 错误,使用 clang 进行编译