Today marked the launch of Eclipse Luna, which is the first version of Eclipse which ships with Java 8 support built in. As we like to stay on the cutting edge here at ZEEF, I decided to give this new version of Eclipse a try straight away.
Unfortunately, I ran into a bug in the Java 8 support fairly quickly. Type inference in Luna seems to fail when the return type of a method needs to be inferred from a lambda within a lambda that has been used as a method parameter. For example, the following code snippet compiles normally using javac, but fails in Eclipse Luna:
Stream.of("test") .flatMap(s -> s.chars().mapToObj(i -> Character.valueOf((char)i))) .filter(Character::isLowerCase) .toArray();
Eclipse seems to infer that the return type of the “i -> Character.valueOf((char)i)” lambda is Object instead of Character, which leads to infer that the return type of flatMap() should be Stream<Object> instead of Stream<Character>. As the method reference used as the filter parameter, the compiler fails on this line as this method reference is not applicable for an argument of type Object.
Fortunately, it’s easy to work around this bug in Eclipse’s compiler. Any change to either the outer or inner lambda which makes the return type explicit allows Eclipse to correctly compile the code. Casting either the inner or the outer lambda to the correct type, assigning either to a variable or replacing either with a method reference allows Eclipse to correctly compile the code. For example, if you were to assign the inner lambda to a variable, you would end up with the following code:
IntFunction<Character> characterFromInt = i -> Character.valueOf((char)i); Stream.of("test") .flatMap(s -> s.chars().mapToObj(characterFromInt)) .filter(Character::isLowerCase) .toArray();
The need to for such a workaround is unfortunate as improved type inference is one of the major enhancements in Java 8. Hopefully a fix for this issue will be available soon.