有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

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


共 (4) 个答案

  1. # 1 楼答案

    对我来说,最简单的方法是定义一个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);
          }
        };
    
    }
    
  2. # 2 楼答案

    您必须在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’s “Interop Between Java and Scala” article

  3. # 3 楼答案

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

    将Java8lambda封装在F(…)然后它被转换成Scala函数

  4. # 4 楼答案

    scala.runtime包中,有一些抽象类命名为AbstractFunction1等等,用于其他算术运算。要从Java中使用它们,只需重写apply,如下所示:

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

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