在Java应用程序中使用groovy.lang.Closure

12

我想在Java应用程序中使用Groovy Closure类,但遇到了比预期更麻烦的问题。这是我的代码:

int count = 0;
groovy.lang.Closure closure = { count = 1 };

然而,当我尝试使用JDK 7编译它时,我收到了错误:illegal initializer for Closure

我是否漏掉了什么非常明显的东西?谢谢你的帮助。


Java不支持闭包语法... - Oliver Charlesworth
2个回答

14

正如Oliver所说,Java不支持这种语法。(免责声明:所有代码未经测试)你可以这样做:

Closure closure = new Closure(null) {
  public Object doCall() {
    /* some code here */
  }
};

但是这样做无法在该方法内设置count,因为这是Java匿名内部类,因此count必须为final。您可以通过任何形式的重定向来绕过此限制,例如使用数组。或者您可以模仿Groovy的做法并使用以下内容:

import groovy.lang.*;
Reference count = new Reference(0);
Closure closure = new Closure(this) {
  public Object doCall() {
    count.set(1);
  }
};

1
为什么要用 doCall 而不是 call? - caeus
有三种调用方法,其中两种调用第三种方法call(Object...)。因此,如果您必须重写其中一种方法,应该是call(Object..),而不是call()。call(Object...)的实现是调用doCall,如果不存在则失败。事实上,我认为即使是重载的doCall方法也可以工作。因此,我个人觉得使用doCall更容易。 - blackdrag

6

以上已有答案,我只是添加一个可行的示例。

Groovy代码接受闭包:

public class GroovyService {

    Integer doSomething(Closure<Integer> fn) {
        fn()
    }
}

从Java中调用Groovy闭包

import groovy.lang.Closure;

public class JavaCanCallGroovy {

    public static void main(String[] args) {

        GroovyService service = new GroovyService();

        Integer data = service.doSomething(new Closure<Integer>(null) { //need to pass owner = null
            @Override
            public Integer call() {
                return 100;
            }
        });

        System.out.println(data);
    }
}

如何从Scala中调用Groovy闭包

import groovy.lang.Closure

object ScalaCanCallGroovy extends App {

  private val closure = new Closure[Integer]() {
    override def call() = 1
  }

  val groovyService = new GroovyService
  val data = groovyService.doSomething(closure)

  assert(data == 1)
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接