将Java Integer绑定到JavaScriptEngine;不起作用

Binding a Java Integer to JavaScriptEngine doesn't work

本文关键字:JavaScriptEngine 不起作用 绑定 Java Integer      更新时间:2023-09-26

为了了解将Java对象绑定到动态语言中的符号是如何工作的,我编写了以下尖峰测试,将java.lang.Integer绑定到要在JavaScript中更改的符号i

  @Test 
  public void bindToLocalVariable() throws ScriptException {
    javax.script.ScriptEngineManager sem 
       = new javax.script.ScriptEngineManager();
    javax.script.ScriptEngine engine 
       = sem.getEngineByName("JavaScript");    
    Integer i = new Integer(17);
    engine.put( "i", i );        
    engine.eval( "i++;" );  // Now execute JavaScript
    assertEquals( 18, i.intValue() );        
    }

不幸的是,我失败了。

java.lang.AssertionError: expected:<18> but was:<17>

JavaScript知道符号i(否则它会抛出一个ScriptException,但事实并非如此),但增量操作i++不会对原始Integer对象执行。

有什么解释吗?

我不知道JavaSrciptEngine,但Integer是不可变的,因此在JavaScript中更改它后,您仍然会有以前的值。

编辑:删除自动装箱以使其更加清晰:

它很像这样:

Integer i = new Integer(17);
Integer j = i;  //should be similar to the assignment in Javascript
j++; //the change to j is not reflected in i
System.out.println(i); //prints 17 not 18

以下是代码中发生的情况:

Integer i = new Integer(17);

这行创建了两个东西:

  • Integer类型的局部变量,名称为i
  • 值为17的新Integer对象

使用对新创建的Integer对象的引用来初始化局部变量(即,它现在指向Integer对象)。

Integer对象不能被修改,因为它是不可变的
局部变量可以通过为其分配新的引用来修改

engine.put( "i", i );

此行将i(它是对Integer对象的引用)传递给方法put()。这意味着put只有知道Integer对象,而不知道变量i。由于Integer对象本身无法修改,因此该方法(或任何其他方法)无法影响存储在局部变量i中的内容。

engine.eval( "i++;" );  // Now execute JavaScript

此方法有效地操纵了前一行创建的JavaScript变量i。该变量被用本地Java变量i的值初始化,但它与本地变量不同。

assertEquals( 18, i.intValue() );      

在这里检查本地Java变量i的值,它是不变的。使断言正确的唯一方法是将其他东西分配给i(例如i = new Integer(18))。

感谢Thomas和Joachim Sauer指出问题是由java.lang.Integer的不变性引起的。

整数通过engine.put()映射到一个真正的JavaScript变量,可以像数字一样处理。如果需要结果,请调用engine.get()将其传递回Java。这与上的List<String>示例不同http://java.sun.com/developer/technicalArticles/J2SE/Desktop/scripting/其中Java对象被传递到脚本,其自己的方法(如Java中定义的)通过回调到Java并使用反射从脚本中应用到它。

一个有趣的细节是,Integer将从JavaScript中检索为Double,这表明确实存在到JavaScript数据对象的前向和后向映射。

这是通过的测试(省略了engine的实例化,它仍然与我的问题中的相同——我在此期间提取了它)。

  @Test 
  public void bindToInteger() throws ScriptException {
    Integer i = 17;
    engine.put( "i", i );        
    engine.eval( "i++" );  // Execute JavaScript
  // i is mapped back to java.lang.Double by get()
    double f = (Double) engine.get("i");  
    assertEquals( 18,  (int) f );        
    }
相关文章:
  • 没有找到相关文章