español - Rhino: los números de Java no se comportan como los números de Javascript
rhino javascript engine download (2)
Esta es una característica extraña de Rhino: un Number
Java configurado con engine.put("one", new Double(1))
funciona como se esperaba, mientras que el resultado de un método Java depende del tipo de retorno declarado por el propio método, que Se lee con la API de reflexión:
- Si es una primitiva, como el
double
, se convierte a un número de Javascript. - de lo contrario, se maneja como otros objetos host y el
+
significa concatenación, ya seaObject
como en su muestra, así comoDouble
Puede configurar este comportamiento con wrapFactory.setJavaPrimitiveWrap(false)
en WrapFactory
en el Context
actual. De esta manera, el código de Rhino se puede mantener en las líneas de arranque de su programa y no saturará a ContentProvider
(que creo que es una especie de proxy de configuración)
Desde el Javadoc en vivo de WrapFactory.isJavaPrimitiveWrap()
De forma predeterminada, el método devuelve verdadero para indicar que las instancias de Cadena, Número, Booleano y Carácter deben incluirse como cualquier otro objeto Java y los scripts pueden acceder a cualquier método Java disponible en estos objetos.
Por lo tanto, puede establecer este indicador en false
para indicar que los Number
Java deben convertirse a números de Javascript. Solo lleva dos líneas de código.
Context ctx = Context.enter();
ctx.getWrapFactory().setJavaPrimitiveWrap(false);
Aquí está la esencia con el código completo que solía probar.
Tengo una instancia de esta clase de Java accesible en mi programa de Javascript
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;
}
}
Este es el código dentro de 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
);
La expresión simple ctx.c(1)
imprime:
rhino:> 1.1 (java.lang.Double)
Ahora, esto es lo que sucede con ctx.c(1) + ctx.c(2)
:
rhino:> 1.12.2 (java.lang.String)
Y finalmente (ctx.c(1) + ctx.c(2)) * ctx.c(3)
:
rhino:> nan (java.lang.Double)
¡Rhino está realizando concatenación de cuerdas en lugar de aritmética numérica! El siguiente programa funciona como se espera en su lugar:
engine.put("a", 1.1);
engine.put("b", 2.2);
engine.put("c", 3.3);
res = engine.eval("(a + b) * c");
Salidas:
rhino:> 10,89 (java.lang.Double)
He creado una envoltura de valor:
public static class JSValue extends sun.org.mozilla.javascript.internal.ScriptableObject
{
Object value;
public JSValue(Object value) {
this.value = value;
}
public String getClassName() {
return value != null? value.getClass().getName(): null;
}
@Override
public Object getDefaultValue(Class typeHint) {
if (typeHint == null || Number.class.isAssignableFrom(typeHint)) {
if (value instanceof Number)
return ((Number) value).doubleValue();
}
return toString();
}
@Override
public String toString() {
return value != null? value.toString(): null;
}
}
y una función de edición:
public static class ContentProvider {
public Object c(int n) {
... return new JSValue(1.1);
Ahora la expresión funciona como se espera. Gracias a todos.