Why does a type request fail for lambda but succeed for an equivalent method reference?

I am using lambda to implement a functional interface in a Java program below. When a lambda is passed as an argument to a generic method, the compiler puts a "incompatible type" error because it indicates that the lambda implements a Func <Shape> interface in which the compiler interprets the lambda parameter (the "thing") as a form type when the lambda tries to pass its method (testRound), which requires an argument of type Round. This error makes sense to me.

But a reference to an equivalent method does not cause an error message. I was misunderstood that the lambda and method reference, which could replace this lambda, were interchangeable. Now, this is not so.

public class Main { public static void main(String... args) { methodB(thing -> Main.testRound(thing)); // incompatible types methodB(Main::testRound); // no problem here } static <T extends Shape> void methodB(Func<T> function) { } static boolean testRound(Round thing) { return true; } } interface Func<T> { boolean test(T ob); } class Shape { } class Round extends Shape { } 

Why does the method link succeed when the lambda is not working?

UPDATE

Vince Amy found the answer, which I designated as accepted below. Although this is not part of my question, here are four ways to get around the fact that lambda is only inferred as the Func<Shape> , if you are really stuck with using lambda:
 // Use a type witness. Main.<Round>methodB(thing -> testRound(thing)); // Make the lambda argument type explicit. methodB((Round thing) -> testRound(thing)); // Cast the argument. methodB(thing -> testRound((Round)thing)); // Store the lambda reference in a Func<Round> variable. Func<Round> lambda = thing -> testRound(thing); methodB(lambda); 

I see no reason to prefer one of them over the method link, unless I feel that lambdas are a little less dense (and maybe a little more readable). But they are there if you want them.

+5
source share
1 answer

From JLS ยง15.13.2 :

Unlike a lambda expression, a method reference can be mapped to a generic function type (that is, a function type that has type parameters). This is because the lambda expression must be able to declare type parameters, and no syntax supports this; while a method reference does not require such an declaration.

The lambda expression throws an error because the type argument is not specified. This causes T compile as Shape (as mentioned in your post), since there is nothing to infer about the type of the argument.

As with method references, since a type can be inferred from method parameters, an explicit type argument is not required, as indicated in the JLS statement above.

+1
source

Source: https://habr.com/ru/post/1260376/


All Articles