在 javax.scripting javascript 环境中导入地图
我在 javax.scripting 地图实现中看到一些奇怪的行为。
在线示例显示了在 js 中添加到列表的 示例环境:
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine jsEngine = mgr.getEngineByName("JavaScript");
List<String> namesList = new ArrayList<String>();
namesList.add("Jill");
namesList.add("Bob");
namesList.add("Laureen");
namesList.add("Ed");
jsEngine.put("namesListKey", namesList);
System.out.println("Executing in script environment...");
try
{
jsEngine.eval("var names = namesListKey.toArray();" + "for(x in names) {" + " println(names[x]);" + "}"
+ "namesListKey.add(\"Dana\");");
} catch (ScriptException ex)
{
ex.printStackTrace();
}
System.out.println(namesList);
但是,如果您尝试对地图执行类似的操作,您会看到奇怪的行为。一方面,如果您尝试迭代映射键,例如,
HashMap<String, Object> m = new HashMap<String, Object>();
jsEngine.put("map", m);
无法获取映射键 - 如果您尝试迭代键,您将获得方法名称 -
jsEngine.eval(" for (var k in m.keySet()){ println(k)};");
结果:
notifyAll
removeAll
containsAll
contains
empty
equals
...
在 js 上下文中,您可以寻址以下值:使用 m.get(key)
获取地图,但不使用 m[key]
获取地图,如果 key 不存在,则会抛出错误。任何人都可以阐明这种行为,还是它只是被破坏了?谢谢。
I'm seeing some odd behavior in the javax.scripting map implementation.
The online examples show an example of adding to a list within the js environment:
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine jsEngine = mgr.getEngineByName("JavaScript");
List<String> namesList = new ArrayList<String>();
namesList.add("Jill");
namesList.add("Bob");
namesList.add("Laureen");
namesList.add("Ed");
jsEngine.put("namesListKey", namesList);
System.out.println("Executing in script environment...");
try
{
jsEngine.eval("var names = namesListKey.toArray();" + "for(x in names) {" + " println(names[x]);" + "}"
+ "namesListKey.add(\"Dana\");");
} catch (ScriptException ex)
{
ex.printStackTrace();
}
System.out.println(namesList);
However, if you try to do something similar with a map, you see odd behavior. For one thing, if you try to iterate through the map keys, e.g.
HashMap<String, Object> m = new HashMap<String, Object>();
jsEngine.put("map", m);
There's no way to obtain the map keys - if you try to iterate through the keys, you get method names-
jsEngine.eval(" for (var k in m.keySet()){ println(k)};");
results in :
notifyAll
removeAll
containsAll
contains
empty
equals
...
In the js context you can address values in the map with m.get(key)
but not with m[key]
, and if the key doesn't exist it throws an error. Can anyone shed some light on this behavior, or is it just broken? Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
JavaScript 中的 for..in 与 Java 中的 for..each 不同,尽管它们看起来很相似。 JavaScript 中的 for..in 迭代对象中的属性名称。方法名称作为本机 Java HashMap 对象上的属性向 Rhino 公开,就像您有以下 JavaScript 对象一样:
我的建议是,您可以使用方法 Set.toArray 将 HashMap 键集转换为数组,或者获取一个使用 Set.iterator() 的迭代器。下面是一个简短的 Rhino 脚本,展示了如何使用 toArray 方法完成此操作:
输出:
以下是如何使用 Set.iterator 完成相同的操作:
for..in in JavaScript is not the same thing as for..each in Java, even though they look similar. for..in in JavaScript iterates over the property names in an object. The method names are exposed to Rhino as properties on the native Java HashMap object, just as if you had the following JavaScript object:
My recommendation is that you either convert the HashMap keyset to an array, using method Set.toArray, or you obtain an iterator using Set.iterator(). Here's a short Rhino script showing how you may accomplish this using the toArray method:
Which outputs:
Here's how you can do the same thing using Set.iterator:
如果将 java.util.Map 转换为本机对象,您的 JavaScript 将更加清晰:
否则,您将陷入标准 Java 语法。
If you convert java.util.Map to a native object, your JavaScript will be cleaner:
Otherwise, you're stuck with standard Java syntax.