You find yourself in a Java 8s character set restriction that applies to the receiver of a method call. While target typing works (in most cases) for parameter types, it does not work for the object or expression to which you call the method.
Here l.stream(). map(n -> () -> { System.out.println(n); return null; }) l.stream(). map(n -> () -> { System.out.println(n); return null; }) is the receiver of the call to the collect(Collectors.toList()) method collect(Collectors.toList()) , therefore the target type List<Callable<Object>> not considered for him.
It is easy to prove that nested lambda expressions work if the type of target is known, for example
static <T> Function<T,Callable<Object>> toCallable() { return n -> () -> { System.out.println(n); return null; }; }
works without problems and you can use it to solve your original problem as
List<Callable<Object>> checks = l.stream() .map(toCallable()).collect(Collectors.toList());
You can also solve the problem by introducing a helper method that changes the role of the first expression from the method receiver to the parameter
and rewrite the original expression as
List<Callable<Object>> checks = collect(l.stream().map( n -> () -> { System.out.println(n); return null; }), Collectors.toList());
This does not reduce the complexity of the code, but can be compiled without any problems. For me it is deja vu. When Java 5 and Generics came out, programmers had to repeat type parameters in new expressions, simply transferring the expression to the general method, proving that type inference does not present a problem. It took until Java 7 before programmers were allowed to skip this unnecessary repetition of type arguments (using the "diamond operator"). Now we have a similar situation, wrapping the call expression in another method, turning the receiver into a parameter, proves that this restriction is not necessary. Therefore, perhaps we will get rid of this limitation in Java 10 ...
Holger Nov 12 '14 at 9:55 a.m. 2014-11-12 09:55
source share