Rhino:Java数字的行为与Javascript数字不同

lun*_*con 17 javascript java rhino

我在我的Javascript程序中可以访问这个Java类的实例

public class ContentProvider {
  public Object c(int n) {
    switch (n) {
      case 1: return 1.1;
      case 2: return 2.2;
      case 3: return 3.3;
      case 4: return "4";
      case 5: return new java.util.Date();
    }
    return null;
  }
}
Run Code Online (Sandbox Code Playgroud)

这是main()中的代码:

ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
engine.put("ctx", new ContentProvider());

res = engine.eval("ctx.c(1)");

System.out.printf("rhino:> %s (%s)%n"
        , res
        , res != null ? res.getClass().getName() : null
);
Run Code Online (Sandbox Code Playgroud)

简单的表达式ctx.c(1)打印:

rhino:> 1.1 (java.lang.Double)
Run Code Online (Sandbox Code Playgroud)

现在这里发生的事情是ctx.c(1) + ctx.c(2):

rhino:> 1.12.2 (java.lang.String)
Run Code Online (Sandbox Code Playgroud)

最后(ctx.c(1) + ctx.c(2)) * ctx.c(3):

rhino:> nan (java.lang.Double)
Run Code Online (Sandbox Code Playgroud)

Rhino正在执行字符串连接而不是数字算术!以下程序按预期工作:

engine.put("a", 1.1);
engine.put("b", 2.2);
engine.put("c", 3.3);
res = engine.eval("(a + b) * c");
Run Code Online (Sandbox Code Playgroud)

输出:

rhino:> 10,89 (java.lang.Double)
Run Code Online (Sandbox Code Playgroud)

Raf*_*ele 5

这是Rhino的一个奇怪特性:Java Number集合engine.put("one", new Double(1))按预期工作,而Java方法的结果取决于方法本身声明的返回类型,使用反射API读取:

  • 如果它是原始的,就像double,它被转换为Javascript号码
  • 否则它会像其他主机对象和+手段连接一样处理,Object就像你的样本一样Double

您可以配置此行为wrapFactory.setJavaPrimitiveWrap(false)WrapFactory当前Context.这样Rhino代码可以保存在程序的引导行中并且不会混乱ContentProvider(我猜是某种配置代理)

来自现场的JavadocWrapFactory.isJavaPrimitiveWrap()

默认情况下,该方法返回true以指示String,Number,Boolean和Character的实例应该包装为任何其他Java对象,并且脚本可以访问这些对象中可用的任何Java方法

因此,您可以将此标志设置false为指示Java Number应转换为Javascript数字.它只需要两行代码

Context ctx = Context.enter();
ctx.getWrapFactory().setJavaPrimitiveWrap(false);
Run Code Online (Sandbox Code Playgroud)

这是我用来测试的完整代码的Gist