【发布时间】:2026-01-29 00:05:01
【问题描述】:
我刚刚发现来自 Java 的 Groovy 调用,并且对这种情况有疑问:
我有一个 groovy 文件:“test.groovy”
a = 1.0
def mul2( x ) { 2.0 * x }
我想像这样从 Java 代码中使用它
GroovyShell gs = new GroovyShell();
gs.parse( new File( ".../test.groovy" ) ).run();
System.out.printf( "a = %s%n", gs.evaluate("a") ); // ok
System.out.printf( "mul2(a) = %s%n", gs.evaluate( "mul2(a)" ) ); // error
错误是:
groovy.lang.MissingMethodException: No signature of method: Script1.mul2() is applicable for argument types: (BigDecimal) values: [1.0]
使用 evaluate() 方法访问 groovy 脚本中定义的函数需要做什么?
我需要使用“评估”方法,因为我想最终评估像Math.sin( a * mul2(Math.Pi) ) 这样的东西。
现在我有 4 个解决方案(第四个是我搜索的):
- 在回答“Szymon Stepniak”时使用闭包
- 使用 import static 作为 'daggett' 的答案
- 使用评估表达式的脚本扩展包含 Java 函数的脚本:
...类(在 Java 中,不是 Groovy)...
public static abstract class ScriptClass extends Script
{
double mul2( double x )
{
return x * 2;
}
}
...代码...
CompilerConfiguration config = new CompilerConfiguration();
config.setScriptBaseClass(ScriptClass.class.getName());
GroovyShell gs = new GroovyShell(config);
System.out.printf( "result = %s%n", gs.evaluate("mul2(5.05)") );
这行得通,但代码是用 Java 编写的,不是我想要的,但我在这里记下了,因为需要这样做的人
- 最后扩展了 groovy 脚本:
groovy 文件:
double mul2( x ) { x * 2 }
a=mul2(3.33)
使用它的java代码
GroovyClassLoader gcl = new GroovyClassLoader();
Class<?> r = gcl.parseClass( resourceToFile("/testx.groovy") );
CompilerConfiguration config = new CompilerConfiguration();
config.setScriptBaseClass(r.getName());
GroovyShell gs = new GroovyShell(gcl, config);
System.out.printf( "mul2(5.05) = %s%n", gs.evaluate("mul2(5.05)") );
// WARNING : call super.run() in evaluate expression to have access to variables defined in script
System.out.printf( "result = %s%n", gs.evaluate("super.run(); mul2(a) / 123.0") );
这正是我想要的:-)
【问题讨论】:
-
您在代码中混入了几个问题。最重要的是:使用
gs.evaluate,您正在解析一个新的 groovy 脚本,并且绝对不会与以前解析的脚本相关联。