放置在变量中的 Java 成员引用比较不相等

问题描述 投票:0回答:1

Java 8 或 Java 11 - 我通过枚举构造函数加载静态函数接口。然后我尝试与相同的成员参考进行比较。代码要么无法编译,要么与相同功能接口的比较失败。使用 .equals 和 == 进行比较以及比较 .hashcode() 都会失败。我创建了以下 POJO 测试来演示该问题并指出有问题的具体点。我想编写“如果实例成员等于特定静态功能接口方法x,则执行...”

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;

import java.util.function.Function;

import org.junit.jupiter.api.Test;

enum MethodReferenceEnum {
    One("One", MethodReferenceInterface::one),
    Two("Two", MethodReferenceInterface::two);

    public String name;
    public Function<String, Integer> method;

    private MethodReferenceEnum(String aName, Function<String, Integer> aMethod) {
        name = aName;
        method = aMethod;
    }
}

interface MethodReferenceInterface {
    public static Integer one(String aString) {
        return 1;
    }
    public static Integer two(String aString) {
        return 2;
    }
}

class MethodRererencesTest {

    @Test
    void LocalUseTest() {
        // This performs in JavaSE-8 (jdk-1.8.0_271) and JavaSE-11 (jdk-11.0.11).

        // These succeed in placing the member references in variables.
        Function<String, Integer> choice1a = MethodReferenceInterface::one;
        Function<String, Integer> choice1b = MethodReferenceEnum.One.method;
        Function<String, Integer> choice2a = MethodReferenceInterface::two;

        // These succeed in executing the member references from variables.
        assertEquals(1, choice1a.apply("A").intValue());
        assertEquals(1, choice1b.apply("B").intValue());
        assertEquals(2, choice2a.apply("2nd").intValue());

        // Why does the following fail to compile?
        //
        // assertEquals(choice1a, MethodReferenceInterface::one);
        //
        // ^ assertEquals fails to compile due to:
        // The method assertEquals(Object, Object) in the type Assert is not applicable
        // for the arguments (Function<String, Integer), MethodReferenceInterface::one)
        // ^ MethodReferenceInterface::one fails to compile due to:
        // The target type of the expression must be a functional interface

        // Compiles and succeeds; expected.
        assertEquals(choice1a, choice1a);

        // This compiles, and succeeds,
        // but why do they not compare equal?
        assertNotEquals(choice1a, choice1b);
    }
}

最后一行和问题总结了这个问题。我运行了上面的测试并且通过了。问题在于,容纳相同成员引用的变量比较不相等。这发生在 Java 8 和 Java 11 中。

java reference functional-interface
1个回答
0
投票

当您输入时:

Function<String, Integer> choice1a  = MethodReferenceInterface::one

编译器将其转换为:

Function<String, Integer> choice1a = new Function<>() {
   String apply(Integer n) {
     return 1;
   }
}

由于成员的类型,它知道将其转换为

Function
接口而不是其他任何东西
choice1a

函数

assertEquals
不是通用函数,它的输入是
object
object
。因此编译器不知道如何创建
MethodReferenceInterface::one

函数的第一个参数

choice1a
并不使函数通用等于(又名
assertEquals(Function, Function)
),但它使它
assertEquals(object, object)

// 编译成功, // 但为什么它们比较不相等呢? 断言不等于(选择1a,选择1b);

它们不等于我最初指定的原因。每次使用

::
快捷方式时,您都会在后台创建一个新实例,并且它们的引用是不同的。

© www.soinside.com 2019 - 2024. All rights reserved.