[英]Using Scala from Java: passing functions as parameters
Consider the following Scala code:考虑以下 Scala 代码:
package scala_java
object MyScala {
def setFunc(func: Int => String) {
func(10)
}
}
Now in Java, I would have liked to use MyScala
as:现在在 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);
}
}
However, the above does not work (as expected since Java does not allow functional programming).但是,上述方法不起作用(正如预期的那样,因为 Java 不允许函数式编程)。 What is the easiest workaround to pass a function in Java?
在 Java 中传递 function 的最简单解决方法是什么? I would like a generic solution that works with functions having arbitrary number of parameters.
我想要一个适用于具有任意数量参数的函数的通用解决方案。
EDIT: Does Java 8 have any better syntax than the classic solutions discussed below?编辑: Java 8 的语法是否比下面讨论的经典解决方案更好?
In the scala.runtime
package, there are abstract classes named AbstractFunction1
and so on for other arities.在
scala.runtime
package 中,有抽象类,名为AbstractFunction1
等,用于其他 arities。 To use them from Java you only need to override apply
, like this:要从 Java 使用它们,您只需覆盖
apply
,如下所示:
Function1<Integer, String> f = new AbstractFunction1<Integer, String>() {
public String apply(Integer someInt) {
return myFunc(someInt);
}
};
If you're on Java 8 and want to use Java 8 lambda syntax for this, check out https://github.com/scala/scala-java8-compat . If you're on Java 8 and want to use Java 8 lambda syntax for this, check out https://github.com/scala/scala-java8-compat .
You have to manually instantiate a Function1
in Java.您必须手动实例化 Java 中的
Function1
。 Something like:就像是:
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);
This is taken from Daniel Spiewak's “Interop Between Java and Scala” article .这摘自Daniel Spiewak 的“Java 和 Scala 之间的互操作”一文。
The easiest way for me is to defined a java interface like:对我来说最简单的方法是定义一个java接口,如:
public interface JFunction<A,B> {
public B compute( A a );
}
Then modify your scala code, overloading setFunc
to accept also JFunction
objects such as:然后修改您的 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) )
}
}
You will naturally use the first definition from scala, but still be able to use the second one from java:您自然会使用 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);
}
};
}
Here's my attempt at a solution, a little library: https://github.com/eirslett/sc8这是我对解决方案的尝试,一个小库: https://github.com/eirslett/sc8
You wrap your Java 8 lambda in F(...) and then it's converted to a Scala function.您将 Java 8 lambda 包装在 F(...) 中,然后将其转换为 Scala ZC1C5D145268E7CA83。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.