Marko对这个问题的评论是正确的。你无法从文件中读取裸的Java lambda表达式,因为没有提供上下文的目标类型定义这样的表达式是无法被定义的。例如,考虑以下方法声明:
void method1(BiFunction<String,String,String> f) { ... }
void method2(BiFunction<Integer,Integer,Integer> f) { ... }
接下来是以下代码:
method1((x, y) -> x + y);
method2((x, y) -> x + y);
这两个lambda表达式 (x, y) -> x + y
表示完全不同的含义。对于method1,+
运算符表示字符串连接,但对于method2,则表示整数相加。
这有点偏离您的问题,但您可以使用动态语言读取和评估lambda或function表达式。在Java 8中,有Nashorn JavaScript引擎。因此,您可以通过从Java调用Nashorn来读取和评估JavaScript函数,而不是尝试读取和评估Java lambda表达式。
以下代码接受arg [0]中的函数并将其应用于每个后续函数,打印结果:
import java.util.function.Function;
import javax.script.*;
public class ScriptFunction {
public static void main(String[] args) throws Exception {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
@SuppressWarnings("unchecked")
Function<Object,Object> f = (Function<Object,Object>)engine.eval(
String.format("new java.util.function.Function(%s)", args[0]));
for (int i = 1; i < args.length; i++) {
System.out.println(f.apply(args[i]));
}
}
}
例如,运行以下命令:
java ScriptFunction 'function(x) 3 * x + 1' 17 23 47
给出结果
52.0
70.0
142.0
将函数字符串包装在 new java.util.function.Function
内是为了在 Nashorn 的 JavaScript 函数观念和 Java 的 Function 接口之间创建一个适配器。(可能有更好的方法,但我不知道。) 将 eval
的返回值强制转换为 Function<Object,Object>
导致了未经检查的强制转换警告,这是不可避免的,因为这是 JavaScript(一种动态类型的语言)和静态类型的 Java 之间的边界。最后,没有进行错误检查。如果违反某些假设,比如第一个参数实际上不表示 JavaScript 函数,则我确定这将以各种恶劣的方式引起问题。
尽管如此,如果您需要评估从文件中读取的表达式或函数,您可能会发现这种技术很有用。