I'm getting this strange exception in code run using 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
What's it mean? The code is as follows:
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);
}
The exception goes away if I change Fruit::getPickingMonth
to x -> x.getPickingMonth()
.
For what it's worth: The exception also goes away if I remove Serializable
from either class. But returns if I add another, equivalent interface to both classes, e.g. Cloneable
or some custom interface.
I believe you are just trying to reference a method from the interface with no return.
ie:
I would imagine you would want something like
Instead
If the above isn't the solution it might be a casting issue where the compiler doesn't know what to return on the bytecode level.
There are questions like this on StackOverflow
Lambda Referencing
Lambda Conversion Exception
You ran into the same compiler bug that has been discussed in this question and that question.
The problem occurs whenever an intersection type is involved and you are using a method reference using a receiver type other than the first one (the first type is the one that will remain after type erasure).
So when you replace the method reference with a lambda expression, you are not affected by the bug anymore. If you remove the
Serializable
from the types instead, the inferred element type of theStream
will beFruit
, i.e. not an intersection type, and again the problem does not occur. But with the two element types implementingFruit
andSerializable
, the compiler will infer the element typeObject&Fruit&Serializable
and the raw type will beObject
which provokes the error when using a method reference with the receiver typeFruit
. You can easily work around this:The compiled code will be identical to your original, but the formal result type of the
flatMap
operation will beStream<Fruit>
, ignoring all other artifacts of the inferred intersection type. As a consequence the method referenceFruit::getPickingMonth
will implement the typeFunction<Fruit,Integer>
instead ofFunction<Object&Fruit&Serializable,Integer>
and the compiler bug does not materialize.But note that your code is unnecessarily complicated. You can simply use
to achieve the same.