2010-08-13 8 views
10

मैं javax.scripting मानचित्र कार्यान्वयन में कुछ अजीब व्यवहार देख रहा हूं।javax.scripting जावास्क्रिप्ट पर्यावरण में मानचित्र आयात करना

ऑनलाइन उदाहरण js पर्यावरण के भीतर एक सूची में जोड़ने के example दिखाने:

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); 

नक्शा कुंजी प्राप्त करने के लिए कोई तरीका नहीं है - अगर आप कुंजी के माध्यम से पुनरावृति करने की कोशिश, आप विधि प्राप्त names-

jsEngine.eval(" for (var k in m.keySet()){ println(k)};"); 

परिणामों में:

notifyAll 
removeAll 
containsAll 
contains 
empty 
equals 
... 

js में संदर्भ आप मानचित्र में m.get(key) के साथ नक्शे में मूल्यों को संबोधित कर सकते हैं लेकिन m[key] के साथ नहीं, और यदि कुंजी मौजूद नहीं है तो यह एक त्रुटि फेंकता है। क्या कोई इस व्यवहार पर कुछ प्रकाश डाल सकता है, या यह सिर्फ टूटा हुआ है? धन्यवाद।

+0

बहुत दिलचस्प है। यह ऑब्जेक्ट्स कुंजीसेट पर राइटर हो सकता है (राइनो में आप विधियों पर लूप कर सकते हैं), लेकिन मुझे यकीन नहीं है। मुझे इसे – TheLQ

उत्तर

12

जावास्क्रिप्ट में for..in जावा में सभी के समान नहीं है, भले ही वे समान दिखते हों। जावास्क्रिप्ट में for..in किसी ऑब्जेक्ट में संपत्ति नामों पर पुनरावृत्त करता है। विधि के नाम निवासी जावा HashMap वस्तु पर गुण के रूप में राइनो के संपर्क में हैं, जैसे कि आपने निम्नलिखित जावास्क्रिप्ट वस्तु था:

{ 
notifyAll:function(){}, 
removeAll:function(){}, 
containsAll:function(){}, 
contains:function(){}, 
empty:function(){}, 
equals:function(){} 
} 

मेरे सिफारिश है कि आप या तो एक सरणी के लिए HashMap कीसेट कनवर्ट करते हैं, विधि सेट का उपयोग करके .toArray, या आप Set.iterator() का उपयोग कर एक इटरेटर प्राप्त करते हैं।

x=new java.util.HashMap(); 
x.put("foo","bar"); 
x.put("bat","bif"); 
x.put("barf","boo"); 

var keyArray = x.keySet().toArray(); 
for(var i=0, l = keyArray.length; i < l; i++){ 
    var key = keyArray[i]; 
    var value = x.get(key); 
    print(value); 
} 

कौन सा आउटपुट:

bif 
bar 
boo 

का तरीका यहां बताया Set.iterator का उपयोग कर एक ही बात कर सकते हैं:

x=new java.util.HashMap(); 
x.put("foo","bar"); 
x.put("bat","bif"); 
x.put("barf","boo"); 

var keyIter = x.keySet().iterator(); 
while(keyIter.hasNext()){ 
    var key = keyIter.next() 
    var value = x.get(key); 
    print(value); 
} 
यहाँ एक छोटी राइनो स्क्रिप्ट तुम ऐसा कैसे पूरा toArray विधि का उपयोग कर सकते हैं दिखा रहा है
+0

धन्यवाद देना होगा, पूरी तरह से और उपयोगी। –

2

यदि आप java.util.Map को मूल ऑब्जेक्ट में कनवर्ट करते हैं, तो आपकी जावास्क्रिप्ट क्लीनर होगी:

final Map<String,String> javaMap = new HashMap<>(); 
javaMap.put("alpha", "bravo"); 
javaMap.put("charlie", "delta"); 

final NativeObject jsMap = new NativeObject(); 
for (Map.Entry<String,String> entry : javaMap.entrySet()) { 
    jsMap.defineProperty(
     entry.getKey(), entry.getValue(), NativeObject.READONLY 
    ); 
} 

final ScriptEngine jsEngine = 
(new ScriptEngineManager()).getEngineByName("JavaScript"); 
jsEngine.put("map", jsMap); 
jsEngine.eval(
    "for (var idx in map) print(idx + '; ' + map[idx] + '\\n');" 
); 

अन्यथा, आप मानक जावा वाक्यविन्यास से फंस गए हैं।

+0

दुर्भाग्य से, आपके मूल ऑब्जेक्ट को या तो राइनो या नैशॉर्न एपीआई होना चाहिए। यह javax.script सामान्य एपीआई में मौजूद नहीं है। – jfrantzius

संबंधित मुद्दे