使用Java的Scala:传递函数作为参数

考虑下面的Scala代码:

package scala_java object MyScala { def setFunc(func: Int => String) { func(10) } } 

现在在Java中,我希望使用MyScala作为:

 package scala_java; public class MyJava { public static void main(String [] args) { MyScala.setFunc(myFunc); // This line gives an error } public static String myFunc(int someInt) { return String.valueOf(someInt); } } 

但是,上述不起作用(正如所料,因为Java不允许function编程)。 在Java中传递函数最简单的解决方法是什么? 我想要一个通用的解决scheme,可以处理具有任意数量参数的函数。

编辑:Java 8有比以下讨论的经典解决scheme更好的语法吗?

您必须手动实例化Java中的Function1 。 就像是:

 final Function1<Integer, String> f = new Function1<Integer, String>() { public int $tag() { return Function1$class.$tag(this); } public <A> Function1<A, String> compose(Function1<A, Integer> f) { return Function1$class.compose(this, f); } public String apply(Integer someInt) { return myFunc(someInt); } }; MyScala.setFunc(f); 

这是来自Daniel Spiewak的“Java和Scala之间的互操作”一文 。

scala.runtime包中,有一些名为AbstractFunction1抽象类,等等。 要从Java使用它们,只需要覆盖apply ,就像这样:

 Function1<Integer, String> f = new AbstractFunction1<Integer, String>() { public String apply(Integer someInt) { return myFunc(someInt); } }; 

如果您使用的是Java 8,并且希望使用Java 8 lambda语法,请查看https://github.com/scala/scala-java8-compat

对我来说最简单的方法是定义一个java接口,如:

 public interface JFunction<A,B> { public B compute( A a ); } 

然后修改你的scala代码,重载setFunc也接受JFunction对象,例如:

 object MyScala { // API for scala def setFunc(func: Int => String) { func(10) } // API for java def setFunc(jFunc: JFunction[Int,String]) { setFunc( (i:Int) => jFunc.compute(i) ) } } 

您将自然使用scala的第一个定义,但仍然可以使用第二个来自java的定义:

 public class MyJava { public static void main(String [] args) { MyScala.setFunc(myFunc); // This line gives an error } public static final JFunction<Integer,String> myFunc = new JFunction<Integer,String>() { public String compute( Integer a ) { return String.valueOf(a); } }; } 

这是我的解决scheme,一个小图书馆的尝试: https : //github.com/eirslett/sc8

将Java 8 lambda包装在F(…)中,然后将其转换为Scala函数。