简体   繁体   English

Java Lambda 表达式是否类似于 Groovy 闭包的逻辑?

[英]Is Java Lambda expression is similar logic of Groovy closure?

I'm learning about Java 8 new feature Lambda expressions .我正在学习 Java 8 新功能Lambda 表达式 This is my "HelloWorld" class using Lambda expression这是我使用 Lambda 表达式的“HelloWorld”类

public class LambdaHelloWorld {
    interface HelloWorld {
        String sayHello(String name);
    }

    public static void main(String[] args) {          
         HelloWorld helloWorld = (String name) -> { return "Hello " + name; };
         System.out.println(helloWorld.sayHello("John Doe"));
    }
}

This style is so similar to Groovy closure.这种风格与 Groovy 闭包非常相似。 This is groovy "HelloWorld"这是时髦的“HelloWorld”

def sayHello(name) {
        println("Hello $name!")
}

def clos = {name -> sayHello(name)} 
clos.call('John Doe')

I think these two codes are less difference between each others.Is Java Lambda expression is similar logic or style of Groovy closure?我认为这两个代码彼此之间的差异较小。Java Lambda表达式是否类似于Groovy闭包的逻辑或风格?

Implementing a so-called functional interface in Java 8 (with lambdas) or in Groovy (with closures) looks quite the same, but underlying mechanisms are pretty different.在 Java 8(使用 lambdas)或 Groovy(使用闭包)中实现所谓的函数式接口看起来完全相同,但底层机制却大不相同。 Let's take the java.util.function.Consumer functional interface as an example.我们以java.util.function.Consumer函数式接口为例。 We use it to call the new Java 8 forEach() method on a hypothetic java.util.List instance called myList .我们使用它在名为myList的假设java.util.List实例上调用新的 Java 8 forEach()方法。

In Java it looks like this:在 Java 中,它看起来像这样:

myList.forEach ((s) -> System.out.println(s));

The same in Groovy:在 Groovy 中也是如此:

myList.forEach { s -> println s }

Both compilers generate new Classes from the lambda / closure code.两个编译器都从 lambda / 闭包代码生成新类。 The class generated by Java 8 implements the target interface ( Consumer in this case), not derived from anything, similar to an embedded anonymous class like this: Java 8 生成的类实现了目标接口(在本例中为Consumer ),不是从任何东西派生出来的,类似于这样的嵌入式匿名类:

myList.forEach(new Consumer<Object>() {
    @Override
    public void accept (Object s) {
        System.out.println(s);
    }
});

In contrast, what Groovy generates looks a little bit like the following:相比之下,Groovy 生成的内容看起来有点像以下内容:

myList.forEach (new Closure(this) {
    void doCall(Object s) {
        println s
    }
}

This creates an anonymous class derived from groovy.lang.Closure that does not implement any specific interface.这将创建一个从groovy.lang.Closure派生的匿名类,它没有实现任何特定的接口。 Nevertheless, it can be used as parameter here.尽管如此,它可以在这里用作参数。 This is possible because Groovy generates a dynamic proxy object at runtime, implementing the ´Consumer´ interface and forwarding any calls to the generated Closure instance.这是可能的,因为 Groovy 在运行时生成动态代理对象,实现“Consumer”接口并将任何调用转发到生成的 Closure 实例。

As a consequence, you can replace Java 8 lambdas by Groovy closures, but not the other way round.因此,您可以用 Groovy 闭包替换 Java 8 lambdas,但不能反过来。 When you want to use a Groovy API in Java 8 code, you cannot call a method expecting a Closure with a lambda expression.当您想在 Java 8 代码中使用 Groovy API 时,您不能使用 lambda 表达式调用需要闭包的方法。 Closure isn't a functional interface but an abstract class, and that can simply not be implemented by a lambda expression. Closure不是函数式接口,而是抽象类,并且它不能由 lambda 表达式实现。

Java's lambdas are closures as well. Java 的 lambdas 也是闭包。 These are the same feature on an abstract level, but in detail and depending on exact version, Groovy may just be creating ad-hoc implementing classes, whereas Java 8 specifies a complete mechanism, consisting of lambda Metafactory, lambda factory, and a mechanism involving invokedynamic to acquire the lambda Metafactory.这些在抽象层面上是相同的特性,但在细节上并取决于确切的版本,Groovy 可能只是创建临时实现类,而 Java 8 指定了一个完整的机制,由 lambda Metafactory、lambda factory 和一个机制组成invokedynamic获取拉姆达Metafactory。

I wanted a simple local closure to pass / execute.我想要一个简单的本地闭包来传递/执行。 I never found this answer anywhere, so adding my spin, so you can see actual mapping from local groovy closure to local java lambda.我从来没有在任何地方找到这个答案,所以添加我的自旋,这样你就可以看到从本地 groovy 闭包到本地 java lambda 的实际映射。

Groovy:常规:

def clos = {name -> sayHello(name)} 
clos('John Doe')

Java:爪哇:

Consumer<String> clos = name -> sayHello(name);
clos.accept("John Doe");

The key being that bloody Consumer interface with accept() method to invoke - you must match the params and return type of your Java lambda based on their pre-canned Function interfaces (java.util.function.*).关键是带有要调用的 accept() 方法的血腥消费者接口 - 您必须根据它们的预装函数接口 (java.util.function.*) 匹配 Java lambda 的参数和返回类型。 That bit is a drag, compared to untyped Groovy version.与无类型的 Groovy 版本相比,这一点是一个阻力。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM