groovy 中的闭包与 java 8 中的闭包(lambda 表达式)?

2022-09-04 02:14:03

鉴于doSomething(Function foo) { println foo(2) }

槽的:doSomething( { it*it } as Function )

爪哇岛:doSomething( (x) -> x*x )

两者之间有什么区别吗?


答案 1

在Groovy中,闭包是类型的一等公民,而Java 8中的lambda是它们表示的默认方法接口的实际实例。groovy.lang.Closure

这意味着您需要在Groovy中使用关键字(如您所展示的),但是或者,在Java中,您需要指定一个接口,因此在Groovy中,您可以执行以下操作:as

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 ) ;
    }
}

显然,您现在还可以在接口中声明默认实现,我在这里没有显示...

不确定这是否是所有差异,但至少是差异;-)


答案 2
  • 在 Java Lambda 表达式中,无法通过默认名称引用 lambda 表达式的参数。在Groovy中也有类似的东西,我认为是“它”。
  • 在 Java 中,Lambda 表达式表示实现单抽象方法类/接口的便捷方法。因此,如果您必须为某些内容创建一个lambda表达式,则必须为其定义一个SAM接口。
  • 在 Java 中,Lambda 表达式只能捕获那些实际上是最终的变量。
  • 在 Java 中,有一种通过使用称为方法引用的东西来表示 Lambda 表达式的另一种方法。因此,如果您有一些像lambda表达式这样的表达式,则可以将其编写为.我认为并非所有 lambda 表达式都可以使用方法引用来表示。{() -> new MyObject();}MyObject::new

我不认为将Java 8中的lambda表达式支持与更成熟的Groovy或Scala支持进行比较是不理想的。这是Java引入lambda表达式的第一步,因此我们可以期望对lambda表达式提供更成熟的支持。