Java 访问未定义值后Nashorn中的输出不一致

Java 访问未定义值后Nashorn中的输出不一致,java,nashorn,Java,Nashorn,我正在尝试使用Nashorn创建Java程序的控制台接口。因此,我希望根据一些默认导入对一些输入进行评估。问题是当它访问未定义的值时。理想情况下,engine.eval应该抛出一个ReferenceError,或者返回null,但我稍后会得到不一致的值: import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; public class Main { public static void mai

我正在尝试使用Nashorn创建Java程序的控制台接口。因此,我希望根据一些默认导入对一些输入进行评估。问题是当它访问未定义的值时。理想情况下,
engine.eval
应该抛出一个
ReferenceError
,或者返回
null
,但我稍后会得到不一致的值:

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

public class Main {
    public static void main(String[] args) throws Exception {
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
        System.out.println(engine.eval("with(JavaImporter(java.util)) { x }"));
        System.out.println(engine.eval("with(JavaImporter(java.util)) { x = 1 }"));
        System.out.println(engine.eval("with(JavaImporter(java.util)) { x }"));
    }
}
在Windows和Oracle JDK 1.8.0_101上的结果是:

null
1
null
最后一个输出是
null
,但是添加
x==null
会得到false

如果在第一个字符串中添加空格,则会得到此输出:

null
1
1
如果第一个和最后一个
engine.eval
参数(包括空格)完全相同,则最后一个值似乎是
null

x
的值可以返回到
null
1
之间,因此它看起来像引擎中的某种缓存:

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

public class Main {
    public static void main(String[] args) throws Exception {
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
        System.out.println(engine.eval("with(JavaImporter(java.util)) { x }"));
        System.out.println(engine.eval("with(JavaImporter(java.util)) { x = 1 }"));
        System.out.println(engine.eval("with(JavaImporter(java.util)) { x }"));
        System.out.println(engine.eval("with(JavaImporter(java.util)) { x  }"));
        System.out.println(engine.eval("with(JavaImporter(java.util)) { x + x }"));
        System.out.println(engine.eval("with(JavaImporter(java.util)) { x }"));
    }
}
给出:

null
1
null
1
2.0
null

是否有办法使其一致地给出
null,1,1
结果?

强制引擎确认变量的声明

只需在第一个脚本中使用
var x

System.out.println(engine.eval(“with(JavaImporter(java.util)){var x}”);
System.out.println(engine.eval(“with(JavaImporter(java.util)){x=1}”);

System.out.println(engine.eval(“with(JavaImporter(java.util)){x}”)

强制引擎确认变量的声明

只需在第一个脚本中使用
var x

System.out.println(engine.eval(“with(JavaImporter(java.util)){var x}”);
System.out.println(engine.eval(“with(JavaImporter(java.util)){x=1}”);

System.out.println(engine.eval(“with(JavaImporter(java.util)){x}”)

引擎中有一个类缓存,可以通过以下方式创建它来禁用它:

NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
ScriptEngine engine = factory.getScriptEngine(new String[] { "--class-cache-size = 0" });

通过强制重新编译每个表达式,似乎可以解决问题。根据作用域中的变量,同一表达式的编译方式似乎有所不同。

引擎中有一个类缓存,可以通过以下方式将其禁用:

NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
ScriptEngine engine = factory.getScriptEngine(new String[] { "--class-cache-size = 0" });

通过强制重新编译每个表达式,似乎可以解决问题。根据作用域中的变量,同一表达式的编译方式似乎有所不同。

x
的值未定义,而不是null。它只是通过
engine.eval
转换为null,以便将其返回到java。你有没有试过
x===未定义的
(注意
===
而不是
==
==
在javascript中只是…不好。它有非常不一致的行为)?。我使用
=
来包含它是
未定义的
空的可能性,但我使用什么代码并不重要,任何更改,它将再次被视为
1
。将
x
替换为
x+x
得到2,甚至在
x
周围添加空格也得到1。这就像字符串的结果被引擎缓存,它忽略了对值的任何更改。我认为这可能是nashorn在返回到非严格模式时出现的错误(尽管我没有找到任何引用)。重要的是要注意,
with(…){…}
语法已被弃用,并且不受
的“use strict”支持。完全删除
with
语句会使nashorn抱怨变量未声明。
x
的值未定义,不是null。它只是通过
engine.eval
转换为null,以便将其返回到java。你有没有试过
x===未定义的
(注意
===
而不是
==
==
在javascript中只是…不好。它有非常不一致的行为)?。我使用
=
来包含它是
未定义的
空的可能性,但我使用什么代码并不重要,任何更改,它将再次被视为
1
。将
x
替换为
x+x
得到2,甚至在
x
周围添加空格也得到1。这就像字符串的结果被引擎缓存,它忽略了对值的任何更改。我认为这可能是nashorn在返回到非严格模式时出现的错误(尽管我没有找到任何引用)。重要的是要注意,
with(…){…}
语法已被弃用,并且不受
的“use strict”支持。完全删除
with
语句会使nashorn抱怨没有声明变量。