java - LambdaConversionException with generics: JVM bug? -


i have code method reference compiles fine , fails @ runtime.

the exception so:

caused by: java.lang.invoke.lambdaconversionexception: invalid receiver type class redacted.basicentity; not subtype of implementation type interface redacted.hasimagesentity     @ java.lang.invoke.abstractvalidatinglambdametafactory.validatemetafactoryargs(abstractvalidatinglambdametafactory.java:233)     @ java.lang.invoke.lambdametafactory.metafactory(lambdametafactory.java:303)     @ java.lang.invoke.callsite.makesite(callsite.java:289) 

the class so:

class imagecontroller<e extends basicentity & hasimagesentity> {     void dothething(e entity) {         set<string> filenames = entity.getimages().keyset().stream()             .map(entity::filename)             .collect(collectors.toset());     } } 

the exception thrown trying resolve entity::filename. filename() declared on hasimagesentity. near can tell, exception because erasure of e basicentity , jvm doesn't (can't?) consider other bounds on e.

when rewrite method reference trivial lambda, fine. seems fishy me 1 construct works expected , semantic equivalent blows up. possibly in spec? i'm trying hard find way not problem in compiler or runtime, , haven't come anything.

here simplified example reproduces problem , uses core java classes:

public static void main(string[] argv) {     system.out.println(dummy("foo")); } static <t extends serializable&charsequence> int dummy(t value) {     return optional.ofnullable(value).map(charsequence::length).orelse(0); } 

your assumption correct, jre-specific implementation receives target method methodhandle has no information generic types. therefore thing sees raw types mismatch.

like lot of generic constructs, there type cast required on byte code level doesn’t appear in source code. since lambdametafactory explicitly requires direct method handle, method reference encapsulates such type cast cannot passed methodhandle factory.

there 2 possible ways deal it.

first solution change lambdametafactory trust methodhandle if receiver type interface , insert required type cast in generated lambda class instead of rejecting it. after all, similar parameter , return types already.

alternatively, compiler in charge create synthetic helper method encapsulating type cast , method call, if had written lambda expression. not unique situation. if use method reference varargs method or array creation like, e.g. string[]::new, can’t expressed direct method handles , end in synthetic helper methods.

in either case, can consider current behavior bug. obviously, compiler , jre developers must agree on way should handled before can on side bug resides.


Comments