FULL PRODUCT VERSION : java version "1.8.0_20" Java(TM) SE Runtime Environment (build 1.8.0_20-b26) Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode) ADDITIONAL OS VERSION INFORMATION : Linux 3.13.0-24-generic #47-Ubuntu SMP Fri May 2 23:30:00 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux EXTRA RELEVANT SYSTEM CONFIGURATION : Also reproducable on windows 7, not tested elsewhere A DESCRIPTION OF THE PROBLEM : When trying to apply a map() using a Function over a multi-bounded intersection generic type, the JRE fails with error message Caused by: java.lang.invoke.LambdaConversionException: Type mismatch for lambda argument 0: interface B is not convertible to interface A STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : Run the main method in the code EXPECTED VERSUS ACTUAL BEHAVIOR : EXPECTED - No error message ACTUAL - java.lang.invoke.LambdaConversionException: Type mismatch for lambda argument 0: interface B is not convertible to interface A ERROR MESSAGES/STACK TRACES THAT OCCUR : java.lang.invoke.LambdaConversionException: Type mismatch for lambda argument 0: interface B is not convertible to interface A REPRODUCIBILITY : This bug can be reproduced always. ---------- BEGIN SOURCE ---------- import java.util.Arrays; import java.util.Comparator; import java.util.List; import static java.util.stream.Collectors.toList; public class Main { public static void main(String[] args) { Main main = new Main(); main.toInfoListError(Arrays.asList(new Base())); } public <H extends B & A> List<Info> toInfoListError(List<H> list) { Comparator<B> byNameComparator = (B b1, B b2) -> b1.getB().compareToIgnoreCase(b2.getB()); return list.stream().sorted(byNameComparator).map(Info::new).collect(toList()); } public <H extends B & A> List<Info> toInfoListWorks(List<H> list) { Comparator<B> byNameComparator = (B b1, B b2) -> b1.getB().compareToIgnoreCase(b2.getB()); return list.stream().sorted(byNameComparator).map(s -> new Info(s)).collect(toList()); } } interface B { public String getB(); } interface A { public long getA(); } class Info { private final long a; private final String b; <H extends A & B> Info(H h) { a = h.getA(); b = h.getB(); } } class Base implements A, B { @Override public long getA() { return 7L; } @Override public String getB() { return "hello"; } } ---------- END SOURCE ---------- CUSTOMER SUBMITTED WORKAROUND : Option A: Swap interfaces: replace <H extends B & A> to <H extends A & B> in method toInfoListError Order of the interfaces in the definition does not seem to bother the lambda used in method toInfoListWorks() though Option B: Use a lambda instead of a Function, cfr method toInfoListWorks()
|