13

我在 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 函数吗?

4

2 回答 2

7

你是什​​么意思,使用这种类型的对象作为可调用的 lambdas?

非常简单的情况下,Java 8 lambda可以被认为是语法糖 + 某些类型接口的匿名类的某种类型推断,即功能接口 [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();
    }
};

所以你的问题只能用以下方式解释:是否可以IFn使用 Java 8 lambda 语法创建类型的对象?

答案是不。Lambda 语法仅适用于函数式接口。clojure.lang.IFn不是功能接口,因为它包含的不仅仅是单一方法,所以不可能做类似的事情

IFn f = (String s) -> s.toLowerCase();
于 2013-01-22T08:57:05.457 回答
2

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

于 2017-04-11T15:49:12.157 回答