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

时间:2014-08-29 09:02:46

标签: java groovy lambda java-8

我了解了java 8新功能 Lambda表达式。所以这是我使用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"));
    }
}

这种样式与Groovy闭包非常相似。这是时髦的“HelloWorld”

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

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

我认为这两个代码之间的差异较小。是不是Java Lambda表达式与Groovy闭包的逻辑或风格相似?

3 个答案:

答案 0 :(得分:14)

在Java 8(使用lambdas)或Groovy(使用闭包)中实现所谓的功能接口看起来完全相同,但底层机制却截然不同。我们以java.util.function.Consumer功能界面为例。我们使用它在名为forEach()的假设java.util.List实例上调用新的Java 8 myList方法。

在Java中它看起来像这样:

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

在Groovy中也一样:

myList.forEach { s -> println s }

两个编译器都从lambda / closure代码生成新的类。 Java 8生成的类实现了目标接口(在本例中为Consumer),而不是从任何东西派生的,类似于嵌入式匿名类,如下所示:

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

相比之下,Groovy生成的内容看起来有点像:

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

这会创建一个派生自groovy.lang.Closure的匿名类,它实现任何特定接口。不过,它可以在这里用作参数。这是可能的,因为Groovy在运行时生成动态代理对象,实现'Consons'接口并转发对生成的Closure实例的任何调用。

因此,您可以通过Groovy闭包替换Java 8 lambdas,但不能反过来。如果要在Java 8代码中使用Groovy API,则无法调用期望具有lambda表达式的Closure的方法。 Closure不是一个功能接口,而是一个抽象类,并且不能通过lambda表达式实现。

答案 1 :(得分:4)

Java的lambdas也是闭包。这些在抽象级别上是相同的功能,但是详细地并且取决于确切的版本,Groovy可能只是创建临时实现类,而Java 8指定了一个完整的机制,包括lambda Metafactory,lambda工厂和涉及的机制。 invokedynamic获得lambda Metafactory。

答案 2 :(得分:1)

我想要一个简单的本地闭包来传递/执行。我从没在任何地方找到此答案,因此添加了自旋,因此您可以看到从本地groovy闭包到本地Java lambda的实际映射。

时髦:

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

Java:

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

关键是要调用带有accept()方法的流血的Consumer接口-您必须根据Java lambda的预定义的Function接口(java.util.function。*)来匹配参数和返回类型。与未键入的Groovy版本相比,这有点麻烦。