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 中。
当您输入时:
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);
它们不等于我最初指定的原因。每次使用
::
快捷方式时,您都会在后台创建一个新实例,并且它们的引用是不同的。