49

考虑以下 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 不允许函数式编程)。在 Java 中传递函数最简单的解决方法是什么?我想要一个适用于具有任意数量参数的函数的通用解决方案。

编辑:Java 8 的语法是否比下面讨论的经典解决方案更好?

4

4 回答 4

74

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

于 2011-12-05T03:29:04.310 回答
27

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

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 之间的互操作”一文

于 2011-07-01T08:05:51.690 回答
7

对我来说最简单的方法是定义一个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);
      }
    };

}
于 2011-07-01T08:01:29.663 回答
0

这是我对解决方案的尝试,一个小库:https ://github.com/eirslett/sc8

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

于 2013-09-22T11:17:52.250 回答