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闭包中的this,owner和delegate

错误记录Groovy 闭包使用报错 ( 闭包中不能直接使用外部对象的方法 | 需要先设置 delegate 代理 )

Groovy中的闭包组合

Gradle学习之闭包

Groovy闭包 Closure ( 闭包定义 | 闭包类型 | 查看编译后的字节码文件中的闭包类型变量 )

Groovy 编译器不接受 java 8 Lambda