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

我了解了Java 8新functionLambda表达式 。 所以这是我使用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闭包的逻辑或风格类似?

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

在Java中它看起来像这样:

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

在Groovy中也是如此:

 myList.forEach { s -> println s } 

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

 myList.forEach(new Consumer() { @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在运行时生成动态代理对象,实现“消费者”接口并转发对生成的Closure实例的任何调用。

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

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