JRuby类和Java脚本引擎意外的结果
我正在试验Java脚本引擎和Ruby,在Ruby脚本中设置一些实例变量时遇到了问题。这可能是我对Ruby缺乏了解,或者我对如何在脚本引擎中使用Ruby类缺乏了解。使用以下代码:JRuby类和Java脚本引擎意外的结果,java,ruby,jruby,jsr223,Java,Ruby,Jruby,Jsr223,我正在试验Java脚本引擎和Ruby,在Ruby脚本中设置一些实例变量时遇到了问题。这可能是我对Ruby缺乏了解,或者我对如何在脚本引擎中使用Ruby类缺乏了解。使用以下代码: public class App { public static void main( String[] args ) throws Exception{ ScriptEngineManager sm = new ScriptEngineManager(); ScriptEngi
public class App {
public static void main( String[] args ) throws Exception{
ScriptEngineManager sm = new ScriptEngineManager();
ScriptEngine se = sm.getEngineByName("jruby");
StringBuilder sb = new StringBuilder();
sb.append("class Test\n");
sb.append(" attr_accessor :a, :b\n");
sb.append(" def str\n");
sb.append(" \"#{a}, #{b} is a test.\"\n");
sb.append(" end\n");
sb.append("end\n");
sb.append("o = Test.new\n");
Object o = se.eval(sb.toString());
se.put("@a", "A");
se.put("@b", "B");
System.out.println( ((Invocable) se).invokeMethod(o, "str"));
}
}
我希望输出是“A,B是测试”
相反,输出是',是一个测试'
我应该如何在这段代码中设置变量a,b
编辑:只是为了澄清,理想情况下,我不想通过将变量附加到此StringBuilder来设置变量-这只是为了说明。实际上,我将从某个源代码加载脚本,然后想在该Ruby对象上设置属性并调用方法。我确信我只是错过了其他人都知道的一些关键步骤:)。多亏了Gareth Davis的回答,我发现我可以成功地使用绑定和全局变量,但这并不适用于所有脚本。我真的很感激任何超出“hello world”类型用法的好文章链接,因为我还没有找到任何合适的链接
第二次编辑:这是正在运行的最终代码,其中有一行我知道肯定丢失了:)-
那样不行。设置a&b值的唯一方法是计算
o.a='a'
和o.b='b'
第一种解决方案是修改脚本以填充值,因此:
sb.append("o.a = 'A'\n");
sb.append("o.b = 'B'\n");
sb.append("o");
Object o = se.eval(sb.toString());
根据问题,可以使用以下内容(归功于@Mick Sear):
那样不行。设置a&b值的唯一方法是计算
o.a='a'
和o.b='b'
第一种解决方案是修改脚本以填充值,因此:
sb.append("o.a = 'A'\n");
sb.append("o.b = 'B'\n");
sb.append("o");
Object o = se.eval(sb.toString());
根据问题,可以使用以下内容(归功于@Mick Sear):
谢谢-我希望能够用java参数化脚本,而不是在执行脚本之前乱搞脚本。如果脚本存储在一个地方,参数存储在另一个地方,那么我觉得您最初的方法更有用。Gareth,我尝试了绑定方法,它适用于全局变量,但恐怕它不适用于Ruby类的实例变量。我曾尝试使用绑定将“o”绑定回上下文,但没有成功。无论如何,谢谢。好的,最后解决了。缺少的关键行是:System.setProperty(“org.jruby.embed.localvariable.behavior”,“persistent”);这使得多个eval使用相同的状态。然后,您可以在原始帖子中使用该方法:se.eval(“o.a=\“a\”);作为一个单独的调用。Gareth,既然你给我指出了正确的方向,如果你想重新编辑你的答案并将该系统属性粘贴进去,我会将你的答案标记为正确。谢谢-我希望能够用java参数化脚本,而不是在执行它之前乱搞脚本。如果脚本存储在一个地方,参数存储在另一个地方,那么我觉得您最初的方法更有用。Gareth,我尝试了绑定方法,它适用于全局变量,但恐怕它不适用于Ruby类的实例变量。我曾尝试使用绑定将“o”绑定回上下文,但没有成功。无论如何,谢谢。好的,最后解决了。缺少的关键行是:System.setProperty(“org.jruby.embed.localvariable.behavior”,“persistent”);这使得多个eval使用相同的状态。然后,您可以在原始帖子中使用该方法:se.eval(“o.a=\“a\”);作为一个单独的呼叫。Gareth,既然你给我指出了正确的方向,如果你想重新编辑你的答案并将系统属性粘贴进去,我会将你的答案标记为正确。
System.setProperty("org.jruby.embed.localvariable.behavior", "persistent");
// .. snip
Object o = se.eval(sb.toString());
se.eval("o.a = 'A'");
se.eval("o.b = 'B'");
System.out.println( ((Invocable) se).invokeMethod(o, "str"));