Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the breakdown for Java's lambda syntax?

Please explain the syntax for Java 8's lambda methods.

There are a lot of explanations out there for what lambda functions are, but I can't find a thorough explanation of the syntax, and I am finding it very difficult to learn to replicate the syntax correctly because I don't understand why they're written as they are.

Here's a common case that I run into, courtesy NetBeans:

public static void main(String[] args) {     SwingUtilities.invokeLater(() -> {         new MainAppJFrame();     }); } 

So somehow, the following lambda expression is resolving into an anonymous Runnable object's run() method:

() -> {     // do stuff } 

The -> is the lambda syntax proper, right? And the curly braces are simply containing the anonymous method code. Are the parentheses an empty argument, because in this case we're creating a Runnable.run() method?

This is all rather unclear to me. I assume the compiler knows to instantiate an anonymous Runnable based on the type expected by the SwingUtilities.invokeLater(Runnable) method? What would happen if there were two SwingUtilities.invokeLater methods which differ only in parameter list? Obviously there aren't in this specific case, but it's possible elsewhere:

interface ExampleLambdaConsumer {     public void doSomething(Runnable r);     public void doSomething(java.lang.reflect.Method m); }  class C implements ExampleLambdaConsumer {     // implementations for doSomething methods here      public static void main(String[] args) {         doSomething(() -> {             // lambda method body here         }     } } 
like image 702
muffin Avatar asked Aug 07 '14 21:08

muffin


People also ask

What is the correct syntax of the lambda function?

You use lambda functions when you need a small function for a short time – for example as an argument of a higher order function like map or filter . The syntax of a lambda function is lambda args: expression .

What does Java's lambda expression allow you to do?

Lambda Expressions were added in Java 8. A lambda expression is a short block of code which takes in parameters and returns a value. Lambda expressions are similar to methods, but they do not need a name and they can be implemented right in the body of a method.

What is the structure of lambda expression?

A lambda in Java essentially consists of three parts: a parenthesized set of parameters, an arrow, and then a body, which can either be a single expression or a block of Java code. In the case of the example shown in Listing 2, run takes no parameters and returns void , so there are no parameters and no return value.

How lambda is represented?

Lambda Symbol (λ)

What are the three things that a lambda expression contain?

Lambda expressions have three parts: a list of parameters, and arrow, and a body: (Object o) -> System. out. println(o);


1 Answers

Syntax is:

arguments -> body 

where arguments can be either

  • ()

  • a single variable if the type of that variable can be inferred from the context

  • a sequence of variables, with or without types (or since Java 11, with var), in parentheses.
    Examples: (x), (x, y), (int x, int y), (var x, var y) (Java 11+).
    The following are invalid: (int x, y), (x, var y), (var x, int y)

and body can be either an expression or a {...} block with statements. The expression (other than a method or constructor call) is simply returned, i.e. () -> 2 is equivalent to () -> {return 2;}


In case of lambda expressions like () -> f() (the body is a method or constructor call expression):

  • if f() returns void, they are equivalent to () -> { f(); }

  • otherwise, they are equivalent to either () -> { f(); } or () -> { return f(); }). The compiler infers it from the calling context, but usually it will prefer the latter.

Therefore, if you have two methods: void handle(Supplier<T>) and void handle(Runnable), then:

  • handle(() -> { return f(); }) and handle(() -> x) will call the first one,

  • handle(() -> { f(); } will call the second one, and

  • handle(() -> f()):

    • if f() returns void or a type that is not convertible to T, then it will call the second one

    • if f() returns a type that is convertible to T, then it will call the first one


The compiler tries to match the type of the lambda to the context. I don't know the exact rules, but the answer to:

What would happen if there were two SwingUtilities.invokeLater methods which differ only in parameter list?

is: it depends on what would be those parameter lists. If the other invokeLater had also exactly one parameter and that parameter would be of type that is also an interface with one method of type void*(), well, then it would complain that it cannot figure out which method you mean.

Why are they written as they are? Well, I think it's because syntax in C# and Scala is almost the same (they use => rather than ->).

like image 66
Karol S Avatar answered Sep 28 '22 09:09

Karol S