gpt4 book ai didi

java - 如何使用 Java 中的 "evaluate"方法使用 groovy 脚本中定义的函数

转载 作者:行者123 更新时间:2023-12-05 03:04:24 25 4
gpt4 key购买 nike

我刚刚发现来自 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 个解决方案(第四个是我搜索的):

  1. 使用闭包来回答“Szymon Stepniak”
  2. 在“daggett”的回答中使用 import static
  3. 使用计算表达式的脚本扩展包含 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 编写的,不是我想要的,但我在这里注明,以供需要这样做的人

  1. 最后扩展 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") );

这正是我想要的:-)

最佳答案

有两件事值得解释以了解这里发生的事情。您提供的脚本中有两个不同的范围。

变量 a 存储在 GroovyShell 绑定(bind)对象中,这就是它在每个 gs.evaluate() 调用中可用的原因。看看这个例子:

import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import groovy.lang.Script;

final class ExecuteGroovyScriptExample {

public static void main(String[] args) {
final String script = "a = 1.0 \n" +
"def mul2(x) { 2.0 * x }\n";

final Binding binding = new Binding();

final GroovyShell gs = new GroovyShell(binding);
final Script sc = gs.parse(script);
sc.run();

System.out.printf("binding.getVariable(\"a\") == %s\n", binding.getVariable("a"));
}
}

运行此示例会产生以下输出:

binding.getVariable("a") == 1.0

第二件事是每次 gs.evaluate() 调用都会生成一个新的 groovy.lang.Script 类,它具有完全不同的上下文。这就是为什么调用:

gs.evaluate("mul2(a)")

抛出这样的东西:

Exception in thread "main" groovy.lang.MissingMethodException: No signature of method: Script2.mul2() is applicable for argument types: (BigDecimal) values: [1.0]

因为从 gs.evaluate("mul2(a)") 调用生成的脚本类不包含 mul2(x) 方法。此调用生成的类如下所示:

class Script2 extends groovy.lang.Script {
void run() {
mul2(a)
}
}

但是,从gs.parse(script) 返回的脚本类包含mul2(x) 方法,因此您可以调用它,但不能作为gs .evaluate() 调用,但 Script.invokeMethod(name, args) 代替。像这样:

import groovy.lang.GroovyShell;
import groovy.lang.Script;

final class ExecuteGroovyScriptExample {

public static void main(String[] args) {
final String script = "a = 1.0 \n" +
"def mul2(x) { 2.0 * x }\n";

final GroovyShell gs = new GroovyShell();
final Script sc = gs.parse(script);
sc.run();

System.out.printf("mul2(a) = %s%n", sc.invokeMethod("mul2", gs.evaluate("a")));
}
}

此示例产生以下输出:

mul2(a) = 2.00

看看 mul2(x) 方法是如何被调用的。首先,我们将 gs.parse(script) 返回的脚本存储在 sc 变量中,它允许我们通过以下调用调用此脚本中定义的方法:

sc.invokeMethod("mul2", gs.evaluate("a"));

在这个例子中,我们简单地通过gs.evaluate("a")获取a变量的值,但是你也可以使用binding第一个示例中的对象也是如此。请记住,如果 a 变量定义如下:

def a = 1.0

@groovy.transform.Field
def a = 1.0

它不会再存储在 binding 对象中,在第一种情况下,它定义了脚本的局部变量 a,在第二种情况下,它定义了脚本类字段 一个


或者,如果您想执行以下调用:

gs.evaluate("mul2(a)")

甚至

gs.evaluate("Math.sin( a * mul2(Math.PI))")

您将不得不修改输入 Groovy 脚本文件,并将函数 mul2(x) 定义替换为与 a 变量相同范围内的闭包,以便它被存储在 binding 对象中:

a = 1.0
mul2 = { x -> 2.0 * x }

关于java - 如何使用 Java 中的 "evaluate"方法使用 groovy 脚本中定义的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53047492/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com