Why is lambda return type not checked at compile time?
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 SerializableFunction<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 IntegerFunction<MyInterface, Integer> function = MyInterface::getLength;Builder.of(MyInterface.class).with(function, "I am NOT an Integer");
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");
It is because your generic type parameter R
can be inferred to be Object, i.e. the following compiles:
Builder.of(MyInterface.class).with((Function<MyInterface, Object>) MyInterface::getLength, "I am NOT an Integer");