2014-09-02 57 views
10

此代码:使用`评估'功能。为什么它不起作用?

evaluate ("def test() { println \"Test is successful!\" }") 
test() 

导致异常:

致命:否方法的签名:script1409644336796288198097.test()是适用于参数类型:()值:[] 可能的解决方案:使用([Ljava.lang.Object;),getAt(java.lang.String),使用(java.util.List,groovy.lang.Closure),使用(java.lang.Class,groovy.lang.Closure),等待(long) groovy.lang.MissingMethodException:方法没有签名:script1409644336796288198097.test()适用于参数类型:()values:[] 可能的解决方案:使用([Ljava.lang.Object;),getAt(java.lang.String),use(java.util.List,groovy.lang.Closure),use(java.lang.Class,groovy.lang .Closure),等待(),等待org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:55) (长) ...

我做错了吗?

+0

不要认为你可以在Gstring中定义方法/变量,然后在GString范围之外调用它们。你想做什么?这可能比这更好的方式。 – jk47 2014-09-02 11:13:45

+0

@ jk47,为什么不呢?我需要从文本文件中读取方法定义并执行它。 – user626528 2014-09-02 11:27:07

+0

你想编写一个读取任意函数然后执行它的程序吗?为什么? – jk47 2014-09-02 11:38:44

回答

9

该脚本评估结果为null。你应该返回一些东西或执行脚本并返回结果。

一个例子返回封闭,而不是定义一个方法:

test = evaluate ('return { "Test is successful!" }') 
assert test() == "Test is successful!" 

和实例在脚本执行方法本身:

result = evaluate 'def test() { "eval test" }; return test()' 
assert result == "eval test" 

如果你不能改变脚本代码,您可能parse a class from the script,创建一个新对象,然后执行test()方法:

def parent = getClass().getClassLoader() 
def loader = new GroovyClassLoader(parent) 
def clazz = loader.parseClass('def test() { "new class definition" }'); 

obj = clazz.newInstance() 
assert obj.test() == "new class definition" 
+0

使用前两种方法之一将参数传递给被调用者的任何方式? – user626528 2014-09-03 04:26:41

+0

@ user626528哎呀,抱歉,延迟。您可以使用['binding'](http://groovy.codehaus.org/Embedding+Groovy)传递参数。 – Will 2014-09-15 11:55:45

+0

谢谢 - 非常有帮助。发现我可以稍微改变这一点,以使用此语法从任意文件中加载方法,不一定在类路径中:loader.parseClass(new File(“ - path to file--”)) – 2015-01-09 15:41:58

0

您可以使用ExpandoMetaClass将动态闭包添加到您自己的类中。您需要事先解析字符串,将其分解为函数名,参数和代码。

methodName = "test" 
methodArgs = [] 
methodCode = """println "Hello World!" """ 

this.metaClass."$methodName"{ code, args -> 
    evaluate(code) 
} 

然后,你可以通过做叫它:

"$methodName"(code, arguments) 

test(code, arguments) 

为了让输出Hello World!

你可以阅读更多有关ExpandoMetaClass这里http://groovy.codehaus.org/ExpandoMetaClass

0

如果一个变量有一个未声明的类型,那么it goes into the script binding。绑定对于所有共享数据的方法都是可见的。

evaluate() is a helper method允许使用this脚本绑定作为变量范围对groovy表达式进行动态评估。

在变量绑定中,您可以使用declare a closure,它不接受任何参数,并且必须限制为不带参数的调用。

记住这一切,这里是你的脚本按预期工作。

evaluate ("test = { -> println \"Test is successful!\" }") 
test() 
0

除了所有其他的答案,如果你不想改变你的代码的结构,你可以简单地在你的Groovy字符串的结尾使用return this

lib = evaluate ("def test() { println \"Test is successful!\" }; return this") 
lib.test()