14

Given doSomething(Function foo) { println foo(2) }

Groovy: doSomething( { it*it } as Function )

Java: doSomething( (x) -> x*x )

Is there any difference between the two?

4

2 回答 2

10

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

这意味着您需要as在 Groovy 中使用关键字(如您所示),但是在 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 ) ;
    }
}

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

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

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

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

于 2013-09-25T08:48:16.073 回答