In JavaScript, there's the common pattern of creating an anonymous function and immediately invoking it.
Which is called a Self-executing anonymous function or an immediately-invoked function expression.
With Java 8 lambdas, is there a standard way to replicate this behavior?
Something like (pseudocode):
(() -> doSomething())()
This question asks basically the same question, but for Java 7. I'm explicitly looking for constructs which utilize lambdas.
In JavaScript, there's the common pattern of creating an anonymous function and immediately invoking it.
Which is called a Self-executing anonymous function or an immediately-invoked function expression.
With Java 8 lambdas, is there a standard way to replicate this behavior?
Something like (pseudocode):
(() -> doSomething())()
This question asks basically the same question, but for Java 7. I'm explicitly looking for constructs which utilize lambdas.
Share Improve this question edited Nov 17, 2022 at 18:06 Alexander Ivanchenko 29k6 gold badges28 silver badges52 bronze badges asked Jun 30, 2016 at 11:43 Aljoscha MeyerAljoscha Meyer 6792 gold badges10 silver badges19 bronze badges 11 | Show 6 more comments3 Answers
Reset to default 17Not without declaring the type as well. Since Java is a statically-typed language, and functions are not first class citizens, the compiler needs to know what type your lambda is. A function can't just be free-floating, it always needs to be associated with either a class or an instance of a class.
Runnable r = () -> {
System.out.println("Hello world!");
};
r.run();
But: You can cast the lambda to the Runnable
type, and give the compiler a hint as to what kind of @FunctionalInterface
you're implementing:
((Runnable)() -> {
System.out.println("Hello world!");
}).run();
Or without the braces, which makes it a one-liner:
((Runnable)() -> System.out.println("Hello world!")).run();
I imagine that's about as close as you'll get!
What about something like
((Runnable)(() -> System.out.println("Foobar"))).run();
Java is very different from JavaScript. And Lambda expressions in Java are not the same as Arrow functions in JavaScript.
Java 8 functions which can be expressed as Lambda expressions or Method references should conform to a so-called Functional interface, they can't appear out of nowhere. On the contrary, in JavaScript and TypeScript any behavior can be implemented using Arrow functions.
It's important to keep in mind this difference there's no special type for Java 8 Function, that's why we need Functional interfaces, which are interfaces having a single abstract method. And Lambdas (as well as Method references) are meant to provide an implementation to this interface).
Lambda expressions and Method references have no type by itself (that's a direct consequence of the absence of a Functional type in the Language).
The expressions give no clue to the compiler about their type:
() -> System.out.println("foo")
i -> i * i
Both Lambda expressions and Method references are so-called poly expressions, which means they sensitive to the context in which they appear.
And since Lambdas in have no type by itself and compiler always needs to infer their type based on either:
- Assignment context;
- Invocation context;
- Casting context.
Here's a short quote from the Java Language Specification §15.27. Lambda Expressions
It is a compile-time error if a lambda expression occurs in a program in someplace other than an assignment context (§5.2), an invocation context (§5.3), or a casting context (§5.5).
In case Assignment context, the type specified on the left of the assignment expression tells the compiler what should be the target of the Functional interface to which lambda conforms:
Supplier<String> summer = () -> "fooBar";
Runnable r = () -> doSomething(); // this::doSomething
Here's a few examples of how to provide a Casting context (both statements below are valid):
((Runnable) () -> doSomething()).run();
((Supplier<String>)() -> "FooBar").get().codePoints()
.filter(Character::isUpperCase)
.mapToObj(i -> (char) i)
.forEach(System.out::println);
And here's an illustration of how target type can be provided through the Invocation context:
String str = (() -> "FooBar").get(); // would Not compile
String str = supplier(() -> "FooBar").get(); // works fine
supplier()
:
public static <T> Supplier<T> supplier(Supplier<T> s) {
return s;
}
defineAnonymousClass
was unfortunately ambigous; in this context, saying "anonymous class" at all invariably plays into this pervasive and unhelpful myth. – Brian Goetz Commented Jul 1, 2016 at 13:39