Java can correctly deduce SAM types and allows me to pass a lambda as a substitute to their implementation, but the same mechanism fails when I try to convert one SAM type to another that has the same signature:
public static Supplier<String> saySomething(){
return () -> "Hello";
}
@FunctionalInterface
interface Greeter {
String greet();
}
public static Greeter getGreeting1(){
// this compiles and runs just fine
return () -> saySomething().get();
}
public static Greeter getGreeting2(){
// this fails at compile:
// java: incompatible types: java.util.function.Supplier<java.lang.String> cannot be converted to Greeter
return saySomething();
}
public static Greeter getGreeting3(){
// this compiles without warnings(probably only because a Supplier<String> might
// also implement the Greeter interface, by chance) but if you call it will fail
// at runtime with a java.lang.ClassCastException
return (Greeter) saySomething();
}
I'm trying to understand why the JVM won't let a lambda be treated as one thing here and another thing there, since it just needs to make another SAM conversion for that. I suspect it's because lambdas are promoted to anonymous classes under to hood, but can someone give a definitive answer?
Also, is there any workaround(except wrapping each SAM conversion in another lambda, as in the first example) to allow it to work?