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.Consumer
function接口为例。 我们使用它在名为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
相比之下,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。