Why is lambda return type not checked at compile time?
Its the type inference that is playing its role here. Consider the generic R
in the method signature:
<R> Builder<T> with(Function<T, R> getter, R returnValue)
In the case as listed:
Builder.of(MyInterface.class).with(MyInterface::getLength, "I am NOT an Integer");
the type of R
is successfully inferred as
Serializable, Comparable<? extends Serializable & Comparable<?>>
and a String
does imply by this type, hence the compilation succeeds.
To explicitly specify the type of R
and find out the incompatibility, one can simply change the line of code as :
Builder.of(MyInterface.class).<Integer>with(MyInterface::getLength, "not valid");
In the first example, MyInterface::getLength
and "I am NOT an Integer"
helped to resolve the generic parameters T
and R
to MyInterface
and Serializable & Comparable<? extends Serializable & Comparable<?>>
respectively.
// it compiles since String is a Serializable
Function<MyInterface, Serializable> function = MyInterface::getLength;
Builder.of(MyInterface.class).with(function, "I am NOT an Integer");
MyInterface::getLength
is not always a Function<MyInterface, Integer>
unless you explicitly say so, which would lead to a compile-time error as the second example showed.
// it doesn't compile since String isn't an Integer
Function<MyInterface, Integer> function = MyInterface::getLength;
Builder.of(MyInterface.class).with(function, "I am NOT an Integer");