groovy 中的闭包与 java 8 中的闭包(lambda 表达式)?
Posted
技术标签:
【中文标题】groovy 中的闭包与 java 8 中的闭包(lambda 表达式)?【英文标题】:closures in groovy vs closures in java 8 (lambda expressions)? 【发布时间】:2013-09-21 10:26:04 【问题描述】:给定doSomething(Function foo) println foo(2)
Groovy:doSomething( it*it as Function )
Java:doSomething( (x) -> x*x )
这两者有区别吗?
【问题讨论】:
【参考方案1】:在 Groovy 中,闭包是 groovy.lang.Closure
类型的一等公民,而 Java 8 中的 lambda 是它们所代表的默认方法接口的实际实例。
这意味着您需要在 Groovy 中使用 as
关键字(如您所示),但是在 Java 中您需要指定一个接口,因此在 Groovy 中,您可以这样做:
def adder( int i, Closure cl )
cl( i )
int v = adder( 2 ) i ->
i + 8
assert v == 10
这在 Java 8 中变为:
public class Test
interface MyAdder
int call( int i ) ;
public int adder( int i, MyAdder adder )
return adder.call( i ) ;
public static void main( String[] args )
int v = new Test().adder( 2, (x) -> x + 8 ) ;
System.out.println( v ) ;
显然,您现在还可以在接口中声明默认实现,我没有在这里展示...
不确定这是否是所有的差异,但至少是不同的 ;-)
【讨论】:
“默认方法接口的实例”:我怀疑你的意思是说“单一抽象方法接口的实例”? @LukasEder 不,我的意思是default methods 是的,我了解默认/防御者/扩展方法是什么。但是 lambda 是 SAM 接口/功能接口的实现,无论是否存在一个或多个默认方法... 不需要像MyAdder那样提供新的接口。 Java8中有很多标准接口,涵盖了很多情况。 docs.oracle.com/javase/8/docs/api/java/util/function/…【参考方案2】: 在 Java Lambda 表达式中,无法通过默认名称引用 lambda 表达式的参数。在 Groovy 中有类似的内容,我认为是“它”。 在 Java 中,Lambda 表达式代表了一种实现单一抽象方法类/接口的便捷方式。因此,如果您必须为某项创建 lambda 表达式,则必须为其定义一个 SAM 接口。 在 Java 中,Lambda 表达式只能捕获那些实际上是 final 的变量。 在 Java 中,有另一种表示 Lambda 表达式的方法,即使用称为方法引用的东西。所以如果你有一些像() -> new MyObject();
这样的lambda表达式,它可以写成MyObject::new
。我认为并非所有 lambda 表达式都可以使用方法引用来表示。
我认为将 Java 8 中的 lambda 表达式支持与更成熟的 Groovy 或 Scala 支持进行比较并不理想。这是 Java 引入 lambda 表达式的第一步,因此我们可以期待对 lambda 表达式有更成熟的支持。
【讨论】:
您还可以在 Groovy 中使用&
运算符而不是 ::
来引用方法。以上是关于groovy 中的闭包与 java 8 中的闭包(lambda 表达式)?的主要内容,如果未能解决你的问题,请参考以下文章
错误记录Groovy 闭包使用报错 ( 闭包中不能直接使用外部对象的方法 | 需要先设置 delegate 代理 )