Java 8 有没有办法让Nashorn JSObject的自定义实现与Object.keys()一起工作?
我最近问了这个问题,得到了一个帮助我在项目中走得更远的答案,但我发现了一个局限性,即提供一个我不知道如何解决的自定义JSObject实现 考虑到这个简单的工作JSObject可以处理JS将在其上调用的大多数方法,例如map:Java 8 有没有办法让Nashorn JSObject的自定义实现与Object.keys()一起工作?,java-8,nashorn,Java 8,Nashorn,我最近问了这个问题,得到了一个帮助我在项目中走得更远的答案,但我发现了一个局限性,即提供一个我不知道如何解决的自定义JSObject实现 考虑到这个简单的工作JSObject可以处理JS将在其上调用的大多数方法,例如map: import javax.script.*; import jdk.nashorn.api.scripting.*; import java.util.*; import java.util.function.*; public class scratch_6 {
import javax.script.*;
import jdk.nashorn.api.scripting.*;
import java.util.*;
import java.util.function.*;
public class scratch_6 {
public static void main(String[] args) throws Exception {
ScriptEngineManager m = new ScriptEngineManager();
ScriptEngine e = m.getEngineByName("nashorn");
// The following JSObject wraps this list
List<Object> l = new ArrayList<>();
l.add("hello");
l.add("world");
l.add(true);
l.add(1);
JSObject jsObj = new AbstractJSObject() {
@Override
public Object getMember(String name) {
if (name.equals("map")) {
// return a functional interface object - nashorn will treat it like
// script function!
final Function<JSObject, Object> jsObjectObjectFunction = callback -> {
List<Object> res = new ArrayList<>();
for (Object obj : l) {
// call callback on each object and add the result to new list
res.add(callback.call(null, obj));
}
// return fresh list as result of map (or this could be another wrapper)
return res;
};
return jsObjectObjectFunction;
} else {
// unknown property
return null;
}
}
};
e.put("obj", jsObj);
// map each String to it's uppercase and print result of map
e.eval("print(obj.map(function(x) '\"'+x.toString()+'\"'))");
//PROBLEM
//e.eval("print(Object.keys(obj))");
}
}
import javax.script.*;
导入jdk.nashorn.api.scripting.*;
导入java.util.*;
导入java.util.function.*;
公共课6{
公共静态void main(字符串[]args)引发异常{
ScriptEngineManager m=新ScriptEngineManager();
ScriptEngine e=m.getEngineByName(“nashorn”);
//下面的JSObject包装了这个列表
列表l=新的ArrayList();
l、 加上(“你好”);
l、 添加(“世界”);
l、 添加(真);
l、 增加(1);
JSObject jsObj=新的AbstractJSObject(){
@凌驾
公共对象getMember(字符串名称){
if(name.equals(“map”)){
//返回一个函数接口对象-nashorn会像
//脚本函数!
最终函数JSObjectFunction=回调->{
List res=new ArrayList();
用于(对象对象对象:l){
//对每个对象调用callback并将结果添加到新列表中
res.add(callback.call(null,obj));
}
//作为映射的结果返回新列表(或者这可能是另一个包装器)
返回res;
};
返回jsObjectObjectFunction;
}否则{
//未知属性
返回null;
}
}
};
e、 put(“obj”,jsObj);
//将每个字符串映射到其大写字母,并打印映射结果
e、 eval(“打印(对象映射(函数(x)\”'+x.toString()+'\“'))”;
//问题
//e、 eval(“打印(Object.keys(obj))”;
}
}
如果取消注释调用Object.keys(obj)的最后一行,它将失败,并出现错误。。。不是对象
这似乎是因为Object.keys()[NativeObject.java:376]只检查对象是ScriptObject还是ScriptObjectMirror的实例。如果两者都不是,则抛出notAnObject错误(理想情况下,用户实现的JSObject对象应该完全等同于脚本对象。但是,用户实现的JSObject几乎都是脚本对象,但不完全是。这里有文档记录-> Object.keys就是这样一种中断的情况。但是,如果您只想在对象的javascript迭代支持中实现..,您可以在类中实现JSObject.keySet 示例代码:
import javax.script.*;
import jdk.nashorn.api.scripting.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
ScriptEngineManager m = new ScriptEngineManager();
ScriptEngine e = m.getEngineByName("nashorn");
// This JSObject wraps the following Properties object
Properties props = System.getProperties();
JSObject jsObj = new AbstractJSObject() {
@Override
public Set<String> keySet() {
return props.stringPropertyNames();
}
@Override
public Object getMember(String name) {
return props.getProperty(name);
}
};
e.put("obj", jsObj);
e.eval("for (i in obj) print(i, ' = ', obj[i])");
}
}
import javax.script.*;
导入jdk.nashorn.api.scripting.*;
导入java.util.*;
公共班机{
公共静态void main(字符串[]args)引发异常{
ScriptEngineManager m=新ScriptEngineManager();
ScriptEngine e=m.getEngineByName(“nashorn”);
//此JSObject包装了以下属性对象
Properties props=System.getProperties();
JSObject jsObj=新的AbstractJSObject(){
@凌驾
公共集密钥集(){
返回props.stringPropertyNames();
}
@凌驾
公共对象getMember(字符串名称){
返回props.getProperty(名称);
}
};
e、 put(“obj”,jsObj);
e、 eval(“对于(obj中的i)打印(i,“=”,obj[i])”;
}
}
理想情况下,用户实现的JSObject对象应该完全等同于脚本对象。但是,用户实现的JSObject几乎都是脚本对象,但不完全是。这在这里有文档记录->
Object.keys就是这样一种中断的情况。但是,如果您只想在对象的javascript迭代支持中实现..,您可以在类中实现JSObject.keySet
示例代码:
import javax.script.*;
import jdk.nashorn.api.scripting.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
ScriptEngineManager m = new ScriptEngineManager();
ScriptEngine e = m.getEngineByName("nashorn");
// This JSObject wraps the following Properties object
Properties props = System.getProperties();
JSObject jsObj = new AbstractJSObject() {
@Override
public Set<String> keySet() {
return props.stringPropertyNames();
}
@Override
public Object getMember(String name) {
return props.getProperty(name);
}
};
e.put("obj", jsObj);
e.eval("for (i in obj) print(i, ' = ', obj[i])");
}
}
import javax.script.*;
导入jdk.nashorn.api.scripting.*;
导入java.util.*;
公共班机{
公共静态void main(字符串[]args)引发异常{
ScriptEngineManager m=新ScriptEngineManager();
ScriptEngine e=m.getEngineByName(“nashorn”);
//此JSObject包装了以下属性对象
Properties props=System.getProperties();
JSObject jsObj=新的AbstractJSObject(){
@凌驾
公共集密钥集(){
返回props.stringPropertyNames();
}
@凌驾
公共对象getMember(字符串名称){
返回props.getProperty(名称);
}
};
e、 put(“obj”,jsObj);
e、 eval(“对于(obj中的i)打印(i,“=”,obj[i])”;
}
}
我在JDK JIRA中找到了,上面写着Object.keys()不适用于Java对象,但请注意,本例中的区别在于,我的类正在实现JSObject,这对我来说意味着它应该是兼容的。我还发现它涉及到类似的领域,并实现了一个修复程序,但该修复程序没有涵盖JSObject接口本身。我在JDK JIRA中找到了该对象。keys()不适用于Java对象,但请注意,本例中的区别在于,我的类正在实现JSObject,这对我来说意味着它应该是兼容的。我还发现它涉及一个类似的领域,并实现了一个修复程序,但修复程序没有涵盖JSObject接口本身。不幸的是,我调用了第三方代码使用Object.keys(),这样我就没有选择将其替换为其他内容。是否值得为jdk9添加一个RFE,以便对JSObject进行Object.keys测试,而不仅仅是ScriptObjectMirror?是的,请针对openjdk.RFE文件提交一个bug/RFE,内部审核ID:90493