最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Java 8 Lambdas vs Self-executing Functions in JavaScript - Stack Overflow

programmeradmin0浏览0评论

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
  • 2 Check this answer – Yassin Hajaj Commented Jun 30, 2016 at 11:49
  • 1 @Holger No, lambdas are not implemented as inner classes. – Brian Goetz Commented Jun 30, 2016 at 15:41
  • 3 @Brian Goetz: I didn’t say inner classes. I just said anonymous classes… – Holger Commented Jun 30, 2016 at 15:58
  • 4 @Holger While technically correct, when you say "anonymous classes", 99.999% of the Java ecosystem hears "anonymous class" as defined by the language (i.e., "anonymous inner classes") -- very very few people know what VM-anonymous classes are -- and those who do, probably already know how lambdas are implemented. So, saying "they are implemented using anonymous classes" is guaranteed to confuse anyone who doesn't already know the actual story. Given that you were responding to OD, who almost certainly is thinking "anonymous inner class", makes it even more likely that you'll confuse. – Brian Goetz Commented Jun 30, 2016 at 18:43
  • 2 @Holger By all means feel free to take the discussion offline -- you should know how to reach me. My goal here is in not encouraging the myth that lambdas are "just" sugar for inner classes. They're semantically different (e.g., scoping rules), they're more efficient and optimizable, and they interact with other language features differently (e.g., type inference.) And yet the "lambdas are just inner classes" myth pervades. The name 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
 |  Show 6 more comments

3 Answers 3

Reset to default 17

Not 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;
}
发布评论

评论列表(0)

  1. 暂无评论