Java 8 or Java 11 - I load a static functional interface through an enum constructor. Then I try to compare against the same member reference. Either the code won't compile, or the comparison against the same functional interface fails. Comparisons using .equals, and ==, and comparing .hashcode() all fail. I have created the following POJO Test that demonstrates the issue and points out the specific points in question. I want to code "If instance-member is equal to specific-static-functional-interface-method-x, then do ..."
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);
}
}
The last line and question sum up the issue. I ran the test above and it passed. The issue is that the variables that house the same member references are not comparing equal. This occurs in Java 8 and Java 11.
When you type:
the compiler converts it to:
It knows to convert it to
Functioninterface and not anything else because of the type of the memberchoice1a.The function
assertEqualsis not a generic function and the input of it isobject,object. Therefore the compiler does not know how to createMethodReferenceInterface::one.The first parameter of the function
choice1adoes not make the function generic equals (akaassertEquals(Function, Function)) but it makes itassertEquals(object, object).They are not equal the same reason I specified at first. Each time you use
::short cut, you create a new instance behind the hood and their references are different.