I used to think about java method references as a syntactic sugar which was introduced as an addition to lambda expressions. But apparently it is not the case.
In the example below method reference, unlike lambda expression, produces an error.
Could someone please explain that weird behavior?
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
System.out.println(getMapUsingLanmdaApproach(MyEnum.class)); // works as expected: {1=A, 2=B}
System.out.println(getMapUsingMethodReferenceApproach(MyEnum.class)); // throws java.lang.BootstrapMethodError
}
static <K, V extends Enum<?> & HasProperty<K>> Map<K, V> getMapUsingLanmdaApproach(Class<V> aClass) {
return Stream.of(aClass.getEnumConstants())
.collect(Collectors.toMap(e -> e.getProperty(), Function.identity()));
}
static <K, V extends Enum<?> & HasProperty<K>> Map<K, V> getMapUsingMethodReferenceApproach(Class<V> aClass) {
return Stream.of(aClass.getEnumConstants())
.collect(Collectors.toMap(HasProperty::getProperty, Function.identity()));
}
}
enum MyEnum implements HasProperty<Integer> {
A(1),
B(2);
private final Integer property;
MyEnum(Integer property) {
this.property = property;
}
@Override
public Integer getProperty() {
return property;
}
}
@FunctionalInterface
interface HasProperty<K> {
K getProperty();
}
Result:
{1=A, 2=B}
Exception in thread "main" java.lang.BootstrapMethodError: call site initialization exception
at java.lang.invoke.CallSite.makeSite(CallSite.java:341)
at java.lang.invoke.MethodHandleNatives.linkCallSiteImpl(MethodHandleNatives.java:307)
at java.lang.invoke.MethodHandleNatives.linkCallSite(MethodHandleNatives.java:297)
at Main.getMapUsingMethodReferenceApproach(Main.java:19)
at Main.main(Main.java:10)
Caused by: java.lang.invoke.LambdaConversionException: Invalid receiver type class java.lang.Enum; not a subtype of implementation type interface HasProperty
at java.lang.invoke.AbstractValidatingLambdaMetafactory.validateMetafactoryArgs(AbstractValidatingLambdaMetafactory.java:233)
at java.lang.invoke.LambdaMetafactory.metafactory(LambdaMetafactory.java:303)
at java.lang.invoke.CallSite.makeSite(CallSite.java:302)
... 4 more
I was running the example on the next java versions:
1.8.0_101-b13
1.8.0_131-b11