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

Sai*_*Aye 10 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"));
    }
}
Run Code Online (Sandbox Code Playgroud)

这种风格与Groovy封闭非常相似.这是时髦的"HelloWorld"

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

def clos = {name -> sayHello(name)} clos.call('John Doe')
Run Code Online (Sandbox Code Playgroud)

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

小智 18

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

在Java中它看起来像这样:

myList.forEach ((s) -> System.out.println(s));
Run Code Online (Sandbox Code Playgroud)

在Groovy中也是如此:

myList.forEach { s -> println s }
Run Code Online (Sandbox Code Playgroud)

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

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

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

myList.forEach (new Closure(this) {
    void doCall(Object s) {
        println s
    }
}
Run Code Online (Sandbox Code Playgroud)

这将创建来源于一个匿名类groovy.lang.Closure,它没有实现任何特定的接口.不过,它可以在这里用作参数.这是可能的,因为Groovy在运行时生成动态代理对象,实现"消费者"接口并转发对生成的Closure实例的任何调用.

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

  • 在Java中,您还可以省略单个lambda参数的圆括号:`s - > System.out.println(s)`所以它看起来更像是在Groovy中.此外,Java编译器不*创建一个`Consumer`实现,它只创建一个*方法*来保存lambda的代码.调用该方法的`Consumer`实现是在运行时生成的.这是Java lambda相对于其他方法(比如旧的内部类)的巨大优势,你没有大量的`.class`文件飞来飞去.如果你使用方法引用,`System.out :: println`,甚至不会生成方法. (8认同)
  • @nawfal:甚至可以使用参数,例如 `Foo::new` 而不是 `(x,y)-&gt;new Fo(x,y)` 以及数组,因此流 API 允许类似: `Foo[ ] array =myList.stream().toArray(Foo[]::new);`。更奇特的是,在实例方法中,您可以将“super”调用绑定到函数,例如“list.forEach(super::doSometing);”来为每个元素调用超类方法...... (2认同)

Mar*_*nik 5

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