使用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函数。