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

标签 java lambda java-8

<分区>

是否可以这样做:

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 - 尝试让 isMultiple 正确执行

java - 'static' 关键字在类中的作用是什么?

c++ - 禁止通过引用捕获

java - 从 java.util.function.Function 获取方法名称

c++ - 使用 gcc 捕获 lambda 错误,使用 clang 进行编译

java - 对于 Document 类型,方法 setXmlStandalone(boolean) 未定义

java - 使用泛型避免未经检查的转换