2012-07-31 9 views
9

मुझे जावा क्रमबद्धता से संबंधित एक दिलचस्प समस्या का सामना करना पड़ा है।कंसोलिज़िंग मानचित्र जो कि रचनाकारों में प्रारंभ किए गए हैं

ऐसा लगता है कि अगर मेरे मानचित्र इस तरह परिभाषित किया गया है:

Map<String, String> params = new HashMap<String, String>() {{ 
    put("param1", "value1"); 
    put("param2", "value2"); 
}}; 

और मैं ObjectOutputStream साथ एक फ़ाइल में क्रमानुसार करने का प्रयास करें:

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(outputFile)); 
oos.writeObject(params); 

... मैं java.io. मिल NotSerializableException।

हालांकि, बजाय मैं मानक तरीका नक्शा करने के लिए मूल्यों डाल अगर:

Map<String, String> params = new HashMap<String, String>(); 
params.put("param1", "value1"); 
params.put("param2", "value2"); 

... तो क्रमबद्धता काम ठीक।

क्या कोई मुझे बता सकता है कि ऐसा क्यों होता है और इन बयानों के बीच क्या अंतर है? मुझे लगता है कि उन्हें वही काम करना चाहिए, लेकिन स्पष्ट रूप से मुझे कुछ याद आ रहा है।

उत्तर

10

पहला उदाहरण अज्ञात आंतरिक वर्ग बना रहा है। कैसे ?

Map<String, String> params = new HashMap<String, String>() {}; 

एक नया वर्ग HashMap से प्राप्त बनाना होगा (ध्यान दें निम्नलिखित ब्रेसिज़, जिसमें आप तरीकों डाल सकते हैं, के सदस्यों आदि)

आपका मानचित्र initialisation तो एक initialiser ब्लॉक वाणी इस प्रकार:

Map<String, String> params = new HashMap<String, String>() { 
                  { // here } 
                  }; 

और उसमें आप अपनी आबादी के तरीकों को बुलाते हैं।

यह मुहावरे ठीक है, लेकिन आपको यह पता होना चाहिए कि आप एक नई वस्तु बना रहे हैं, न केवल एक नई वस्तु।

क्योंकि यह कक्षा एक आंतरिक कक्षा है, इसमें अंतर्निहित बाहरी कक्षा में this पॉइंटर होगा। एक धारावाहिक वर्ग से इसकी व्युत्पन्न के कारण आपका अज्ञात वर्ग क्रमबद्ध होगा। हालांकि आपकी बाहरी कक्षा (this पॉइंटर द्वारा संदर्भित) नहीं है।

XStream जैसे उपकरण, जो प्रतिबिंब के माध्यम से एक्सएमएल को क्रमबद्ध करते हैं, this पॉइंटर की खोज करेंगे और आसपास के ऑब्जेक्ट को क्रमबद्ध करने का प्रयास करेंगे, जो कि भ्रमित है।

+1

'स्थिर प्रारंभकर्ता 'से, आपका मतलब' इंस्टेंस प्रारंभकर्ता 'है? –

+0

तो अपेक्षित संलग्न वर्ग क्या होगा? – Shark

+0

@ Eng.Fouad - व्हाउप्स। संशोधित –

0

मैं इस सुझाव से @Brian एग्न्यू के जवाब के पूरक के लिए चाहता था:

मैं एक मामले में जहां मैं एक वस्तु से बाहर थोड़ा अलग व्यवहार की जरूरत थी, इसलिए के रूप में आप में किया था मैं एक गुमनाम आंतरिक वर्ग के साथ अपनी क्षमताओं बढ़ाया उदाहरण। बाहरी वर्ग एक जीयूआई एप्लीकेशन था, और मैंने इसे क्रमबद्ध नहीं किया क्योंकि यह आवश्यक नहीं था, इसलिए @ ब्रियन ने कहा, कोई गुमनाम आंतरिक कक्षाएं धारावाहिक नहीं हो सकती हैं, भले ही वे कक्षाएं विस्तार कर रहे हों।

इस स्थिति में, आपको केवल कक्षा के deserialized के लिए अलग व्यवहार को परिभाषित करना होगा और जब इसे फिर से क्रमबद्ध किया जाता है।आप एक विशिष्ट निर्माता के साथ एक वर्ग है, तो अपनी कक्षा में इस तरह की एक विधि का उपयोग करें:

public FunctionalObject getNewFunctionalObject (String param1, String param2) { 
    // Use an anonymous inner class to extend the behavior 
    return new FunctionalObject (param1, param2) { 
     { 
      // Initialization block code here 
     } 
     // Extended behavior goes here 
    }; 
} 

तो जब आप deserializing कर रहे हैं, तो आप इस तरह एक कॉल कर सकते:

FunctionalObject fo = (FunctionalObject) objectInputStream.readObject(); 
fo = getNewFunctionalObject(fo.getParam1(), fo.getParam2()); 

जब serializing, आपको new ऑब्जेक्ट बनाना होगा जो पुराने ऑब्जेक्ट का क्लोन है। कुछ वर्गों में यह व्यवहार बनाया गया है, और दूसरों में आपको इसे विशेष रूप से परिभाषित करना होगा। क्रमबद्धता लिए, यदि आप एक निर्माता है कि यह क्लोन कर सकते हैं, या यदि आपके वर्ग clone विधि परिभाषित है, तो आप ऐसा कर सकते हैं:

objectOutputStream.writeObject (fo.clone()); 

फिर, उस वस्तु की clone अब के लिए एक संदर्भ हो जाएगा अपने अज्ञात आंतरिक वर्ग, लेकिन ऑब्जेक्ट की वास्तविक प्रति का संदर्भ, जो धारावाहिक है।

अपने उदाहरण के मामले में, आप सिर्फ इस किया जा सकता है:

// Assuming objectOutputStream has already been defined 
Map<String, String> params = new HashMap<String, String>() {{ 
    put("param1", "value1"); 
    put("param2", "value2"); 
}}; 
objectOutputStream.writeObject (new HashMap<String,String> (params)); 

यह काम करता है क्योंकि HashMap वर्ग एक निर्माता है कि एक क्लोन जो कुछ भी की HashMap इसे में पारित हो जाता है वापस आ जाएगी है। यह कुछ आसान कहने के लिए बहुत सारे शब्द थे, लेकिन मेरी इच्छा थी कि मैं जल्द ही यह सलाह लेता।

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