我在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函数?
答案 0 :(得分:7)
你是什么意思,使用这种类型的对象作为可调用的lambdas?
在非常简单的情况下,Java 8 lambdas 可以被认为是语法糖+某些类型接口的匿名类的某种类型推断,即功能接口 [1]:
上面使用的ActionListener接口只有一个方法。许多 常见的回调接口具有此属性,例如Runnable和 比较。我们将给出只有一种方法的所有接口 name:功能接口。
备注:lambdas真的不仅仅是糖;在内部,它们的实现方式与匿名类不同,并且还存在一些语义差异;有关此问题的更多信息,请参阅ProgrammersExchange上的this excellent answer。但是,在这个问题和答案的背景下,这并不重要。
在需要某个函数接口的值的任何地方(方法参数,局部变量,字段声明等),可以使用短语法创建一个实体,该实体类似于实现此方法的匿名类,即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();
答案 1 :(得分:2)
不,似乎你不能使用clojure函数,就好像它们也是有效的java lambdas一样。 Clojure的IFn不符合java定义的“lambda”功能接口。