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()
returnsvoid
, 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(); })
andhandle(() -> x)
will call the first one, -
handle(() -> { f(); }
will call the second one, and -
handle(() -> f())
:-
if
f()
returnsvoid
or a type that is not convertible toT
, then it will call the second one -
if
f()
returns a type that is convertible toT
, 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 ->
).