为什么方法引用会产生java.lang.BootstrapMethodError

时间:2017-07-03 11:17:12

标签: java generics lambda java-stream method-reference

我曾经把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

0 个答案:

没有答案