When a lambda expression is passed to a method it is possible to retrieve its return-type and the parameter-types (if specifically given by the caller) using type-parameters.
What I don't understand is that java seems to discard the type information given by the return-type of a lambda expression if the expression also uses the return-type as a parameter-type.
It is really hard to explain this question with words. Therefore I wrote the sample code below for further clarification.
//Case 1 @FunctionalInterface interface Test<R> { void returnValue(R takes); } static <R> R test(Test<R> test) { //... Do something with test } public static void main(final String[] args) { test((a) -> System.out.println("called")); //This call will always return an Object //This is clear. It is totally unknown which type a has at compile-time } //-------------------------------------------------------------------------- //Case 2 @FunctionalInterface interface Test<R> { R returnValue(); } static <R> R test(Test<R> test) { //... Do something with test } public static void main(final String[] args) { test(() -> " "); //This call will always return a String //This is clear. R is specified to be a String by the return value. } //-------------------------------------------------------------------------- //Case 3 @FunctionalInterface interface Test<R> { R returnValue(R takes); } static <R> R test(Test<R> test) { //... Do something with test } public static void main(final String[] args) { test((a) -> " "); //This call will always return an Object //This it not clear. R is specified to be a String by the return value //Why doesn't it return a String ? } Edit: Going deeper into the problem I noticed that the problem only really occurs when chaining calls. The code below demonstrates this. It was compiled in eclipse using java version 1.8.0_73.
package test; public class TestLambdaGenerics { @FunctionalInterface interface Test<R> { R returnValue(R takes); } static <R> Test<R> test(final Test<R> test) { // ... Do something with test return test; } public static void main(final String[] args) { final Test<String> t = test((a) -> " "); // Above works fine final String t2 = test((a) -> " ").returnValue(" "); // Above terminates with output: // Exception in thread "main" java.lang.Error: Unresolved compilation problem: // Type mismatch: cannot convert from Object to String // // at test.TestLambdaGenerics.main(TestLambdaGenerics.java:18) } } Edit 2:
Question is resolved "chain-calling" with type-inference is just not supported by java at the moment.
See: this question or this article
String b = test((a) -> " ");compiles without issue, so the typeStringis inferred. I don't understand your issue.