2012-09-11 6 views
30
Object[] o = "a;b;c".split(";"); 
o[0] = 42; 

फेंकताएक ArrayStoreException के साथ काम

java.lang.ArrayStoreException: java.lang.Integer 

जबकि

String[] s = "a;b;c".split(";"); 
Object[] o = new Object[s.length]; 
for (int i = 0; i < s.length; i++) { 
    o[i] = s[i]; 
} 
o[0] = 42; 

नहीं करता है।

क्या अस्थायी String[] सरणी बनाये बिना उस अपवाद से निपटने का कोई अन्य तरीका है?

+4

ऑब्जेक्ट [] ओ = "ए; बी; सी"। एसप्लिट (";"); ओ [0] = 42; यहां आप स्ट्रिंग्स की एक सरणी बना रहे हैं, जबकि ऑब्जेक्ट [] ओ = नया ऑब्जेक्ट [एस लम्बाई]; ऑब्जेक्ट्स की एक सरणी है। – Satya

उत्तर

53

जावा में एक सरणी भी ऑब्जेक्ट है।

आप एक महाप्रकार के एक चर में एक उप प्रकार की एक वस्तु डाल सकते हैं। उदाहरण के लिए आप String ऑब्जेक्ट को Object चर में डाल सकते हैं।

दुर्भाग्यवश, जावा में सरणी परिभाषा किसी तरह टूटा हुआ है। String[] को Object[] का उप प्रकार माना जाता है, लेकिन यह गलत है! अधिक विस्तृत स्पष्टीकरण के लिए "covariance और contravariance" के बारे में पढ़ें, लेकिन इसका सार यह है: उप प्रकार टाइप उप-प्रकार के सभी दायित्वों को पूरा करता है, तो एक प्रकार को केवल दूसरे प्रकार का उपप्रकार माना जाना चाहिए। इसका मतलब है कि, अगर आपको सुपरटेप ऑब्जेक्ट की बजाय उप प्रकार ऑब्जेक्ट मिलता है, तो आपको सुपरटेप अनुबंध के व्यवहार के विपरीत व्यवहार की अपेक्षा नहीं करनी चाहिए।

समस्या है कि String[] केवल Object[] अनुबंध की एक हिस्सा समर्थन करता है। उदाहरण के लिए आप ObjectObject[] से मान पढ़ सकते हैं। और आप सेObject मान (जो String ऑब्जेक्ट्स होते हैं) को पढ़ सकते हैं। अब तक सब ठीक है। समस्या अनुबंध के दूसरे हिस्से के साथ है। आप किसी भीObjectObject[] पर डाल सकते हैं। लेकिन आप ObjectString[] पर नहीं डाल सकते हैं। इसलिए, String[] को Object[] का उप-प्रकार नहीं माना जाना चाहिए, लेकिन जावा विनिर्देश कहता है कि यह है। और इस प्रकार हमारे पास इस तरह के परिणाम हैं।

(ध्यान दें कि इसी तरह की स्थिति सामान्य वर्गों के साथ फिर से दिखाई दिया, लेकिन इस बार यह सही ढंग से हल किया गया थाList<String> नहीं है List<Object> की एक उप-प्रकार;। और अगर आप इन के लिए एक आम महाप्रकार करना चाहते हैं, तो आप List<?> की आवश्यकता है, जो केवल पढ़ने के लिए है।इस तरह यह सरणी के साथ भी होना चाहिए; लेकिन ऐसा नहीं है। और पिछली संगतता की वजह से, इसे बदलने में बहुत देर हो चुकी है।)

आपके पहले उदाहरण में String.split फ़ंक्शन String[] ऑब्जेक्ट बनाता है। आप इसे Object[] चर में डाल सकते हैं, लेकिन ऑब्जेक्ट String[] है। यही कारण है कि यह Integer मान को अस्वीकार करता है। आपको एक नया Objects[] सरणी बनाना है, और मानों की प्रतिलिपि बनाना है। डेटा की प्रतिलिपि बनाने के लिए आप System.arraycopy फ़ंक्शन का उपयोग कर सकते हैं, लेकिन आप नई सरणी बनाने से नहीं बच सकते हैं।

+0

http://www.angelikalanger.com/GenericsFAQ/FAQSections/ParameterizedTypes.html#FAQ102 –

6

नहीं, split रिटर्न की सरणी को कॉपी करने से बचने का कोई तरीका नहीं है।

split रिटर्न वास्तव में String[] है, और जावा आपको Object[] प्रकार के चर के लिए असाइन करने की अनुमति देता है। यह अभी भी वास्तव में String[] है, इसलिए जब आप String से कुछ और स्टोर करने का प्रयास करते हैं, तो आपको ArrayStoreException मिल जाएगा।

पृष्ठभूमि जानकारी के लिए जावा भाषा विशिष्टता में 4.10.3. Subtyping among Array Types देखें।

0

निश्चित रूप से अन्य विकल्प हैं, जैसे कि आप अपनी खुद की विभाजित विधि लागू करते हैं, जो सीधे ऑब्जेक्ट सरणी देता है। मुझे यकीन नहीं है कि वास्तव में अस्थायी स्ट्रिंग सरणी के साथ आपको क्या परेशान करता है? यदि यह एक "विभाजित" का उपयोग करने के लिए आवश्यक नहीं है

System.arrayCopy(s, 0, o, 0, s.length); 
-1

..:

BTW, आप System.arrayCopy का उपयोग कर कुछ लाइनें बजाय लागू करने अपनी खुद की पाश सरणी तत्वों की प्रतिलिपि करने के साथ अपने कोड को छोटा कर सकते । तो आप प्रतिलिपि से बच सकते हैं ...

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