我了解了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闭包的逻辑或风格相似?
答案 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版本相比,这有点麻烦。