2.1.2 语言绑定
脚本语言支持API的一个很大优势在于它规范了Java语言与脚本语言之间的交互方式,使Java语言编写的程序可以与脚本之间进行双向的方法调用和数据传递。方法调用的方式会在2.1.5小节中介绍。数据传递是通过语言绑定对象来完成的。所谓的语言绑定对象就是一个简单的哈希表,用来存放和获取需要共享的数据。所有数据都对应这个哈希表中的一个条目,是简单的名值对。接口javax.script.Bindings定义了语言绑定对象的接口,它继承自java.util.Map接口。一个脚本引擎在执行过程中可能会使用多个语言绑定对象。不同语言绑定对象的作用域不同。在默认情况下,脚本引擎会提供多个语言绑定对象,用来存放在执行过程中产生的全局对象等。ScriptEngine类提供了put和get方法对脚本引擎中特定作用域的默认语言绑定对象进行操作。程序可以直接使用这个默认的语言绑定对象,也可以使用自己的语言绑定对象。在脚本语言的执行过程中,可以将语言绑定对象看成是一个额外的变量映射表。在解析变量值的时候,语言绑定对象中的名称也会被考虑在内。脚本执行过程中产生的全局变量等内容,会出现在语言绑定对象中。通过这种方式,就完成了Java与脚本语言之间的双向数据传递。
在代码清单2-2中,首先通过ScriptEngine的put方法向脚本引擎默认的语言绑定对象中添加了一个名为“name”的字符串,接着在脚本中直接根据名称来引用这个对象。同样,在脚本中创建的全局变量“message”也可以通过ScriptEngine的get方法来获取。这样就实现了Java程序与脚本之间的双向数据传递。数据传递过程中的类型转换是由脚本引擎来完成的,转换规则取决于具体的脚本语言的语法。
代码清单2-2 脚本引擎默认的语言绑定对象的示例
public void useDefaultBinding()throws ScriptException{
ScriptEngine engine=getJavaScriptEngine();
engine.put("name","Alex");
engine.eval("var message='Hello,'+name;");
engine.eval("println(message);");
Object obj=engine.get("message");
System.out.println(obj);
}
在大多数情况下,使用ScriptEngine的put和get方法就足够了。如果仅使用put和get方法,语言绑定对象本身对于开发人员来说是透明的。在某些情况下,需要使用程序自己的语言绑定对象,比如语言绑定对象中包含了程序自己独有的数据。如果希望使用自己的语言绑定对象,可以调用脚本引擎的createBindings方法或创建一个javax.script.SimpleBindings对象,并传递给脚本引擎的eval方法,如代码清单2-3所示。
代码清单2-3 自定义语言绑定对象的示例
public void useCustomBinding()throws ScriptException{
ScriptEngine engine=getJavaScriptEngine();
Bindings bindings=new SimpleBindings();
bindings.put("hobby","playing games");
engine.eval("println('I like'+hobby);",bindings);
}
通过eval方法传递的语言绑定对象,仅在当前eval调用中生效,并不会改变引擎默认的语言绑定对象。