我是否能够在Java 8中使用Clojure函数作为Lambdas?

我在Clojure中使用了许多库,这些库生成符合“clojure.lang.IFn”接口的高阶函数。

它具有多个 arity 重载,即接口看起来像这样:

public interface IFn extends Callable, Runnable{
  public Object invoke() ;
  public Object invoke(Object arg1) ;
  public Object invoke(Object arg1, Object arg2) ;
  public Object invoke(Object arg1, Object arg2, Object arg3) ;
  .... etc.
  public Object applyTo(ISeq arglist) ;
}

我是否能够直接在 Java 8 中使用这种类型的对象作为可调用的 lambda 函数?


答案 1

您的意思是,将此类型的对象用作可调用的 lambda?

非常简单的情况下,Java 8 lambdas可以被认为是语法糖+某些类型接口的匿名类的某种类型推断,即功能接口[1]

上面使用的接口 ActionListener 只有一个方法。许多常见的回调接口都具有此属性,例如 Runnable 和 Comparator。我们将为所有只有一个方法的接口命名:功能接口。

备注:lambdas真的不仅仅是一种糖;在内部,它们的实现方式与匿名类不同,并且还存在一些语义差异;在 ProgrammersExchange 上查看这个出色的答案,以获取有关此事的更多信息。但是,在这个问题和答案的背景下,这并不重要。

在需要某些功能接口的值(方法参数,局部变量,字段声明等)的任何地方,都可以使用短语法来创建实体,重新生成实现此方法的匿名类,即lambda表达式:

Runnable r = () -> {
    System.out.println("Hi");
};
// Equivalent to
Runnable r = new Runnable() {
    public void run() {
        System.out.println("Hi");
    }
};

public interface Function<F, T> {
    T call(F arg);
}

Function<String, char[]> c = s -> ("<" + s + ">").toCharArray();
// Equivalent to
Function<String, char[]> c = new Function<>() {
    public char[] call(String s) {
        return ("<" + s + ">").toCharArray();
    }
};

因此,您的问题只能通过以下方式解释:是否可以使用Java 8 lambda语法创建类型的对象?IFn

答案是否定的。Lambda 语法仅适用于功能接口。 不是一个功能接口,因为它包含的不仅仅是单个方法,所以不可能做这样的事情clojure.lang.IFn

IFn f = (String s) -> s.toLowerCase();

答案 2

不,似乎你不能使用clojure函数,就好像它们也是有效的java lambdas一样。Clojure的IFn不符合Java定义的“lambda”函数接口。