我曾经把java方法引用看作是一个语法糖,它是作为lambda表达式的一个补充而引入的。但显然事实并非如此。
在下面的示例中,方法引用与lambda表达式不同,会产生错误 有人可以解释一下奇怪的行为吗?
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();
}
结果:
{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
我在下一个java版本上运行示例:
1.8.0_101-B13
1.8.0_131-B11