我在使用 jre1.8.0_66 运行的代码中遇到了这个奇怪的异常:
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
Caused by: java.lang.invoke.LambdaConversionException: Invalid receiver type class java.lang.Object; not a subtype of implementation type interface Fruit
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)
... 3 more
这是什么意思?代码如下:
public static interface Fruit {
int getPickingMonth();
}
public static class Apple implements Fruit, Serializable {
@Override
public int getPickingMonth() {
return 11;
}
}
public static class Orange implements Fruit, Serializable {
@Override
public int getPickingMonth() {
return 2;
}
}
public static void main(String[] args) {
List<Apple> apples = Arrays.asList(new Apple());
List<Orange> oranges = Arrays.asList(new Orange());
Stream.of(apples.stream(), oranges.stream())
.flatMap(Function.identity())
.map(Fruit::getPickingMonth) // exception occurs on this line
.forEachOrdered(System.out::println);
}
如果我将 Fruit::getPickingMonth
更改为 x -> x.getPickingMonth()
,异常就会消失。
它的值(value):如果我从任一类中删除 Serializable
,异常也会消失。但是,如果我向两个类添加另一个等效接口(interface),则返回,例如Cloneable
或一些自定义界面。
最佳答案
您遇到了在 this question 中讨论过的相同编译器错误和 that question .
每当涉及交集类型并且您使用的方法引用使用的接收器类型不是第一个类型(第一个类型是类型删除后将保留的类型)时,就会出现此问题。
因此,当您将方法引用替换为 lambda 表达式时,您将不再受到该错误的影响。如果删除 Serializable
相反,从类型中推断出 Stream
的元素类型将是 Fruit
,即不是交集类型,问题也不会发生。但是这两种元素类型实现了 Fruit
和 Serializable
,编译器将推断元素类型 Object&Fruit&Serializable
原始类型将是 Object
在使用接收者类型为 Fruit
的方法引用时引发错误.您可以轻松解决此问题:
Stream.of(apples.stream(), oranges.stream())
.<Fruit>flatMap(Function.identity())
.map(Fruit::getPickingMonth) // no more exception on this line
.forEachOrdered(System.out::println);
编译后的代码将与您的原始代码相同,但 flatMap
的正式结果类型操作将是Stream<Fruit>
,忽略推断的交集类型的所有其他工件。因此,方法引用 Fruit::getPickingMonth
将实现类型 Function<Fruit,Integer>
而不是 Function<Object&Fruit&Serializable,Integer>
并且编译器错误没有实现。
但请注意,您的代码不必要地复杂。你可以简单地使用
Stream.<Fruit>concat(apples.stream(), oranges.stream())
.map(Fruit::getPickingMonth) // no more exception on this line
.forEachOrdered(System.out::println);
实现相同。
关于java - 奇怪的异常 "Invalid receiver type class java.lang.Object; not a subtype of ...",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33929304/