2012-12-08 17 views
7

जावा ArrayList<E> ऑब्जेक्ट्स की सरणी पर कार्यान्वयन आधार।
क्या कोई मुझे बता सकता है कि ArrayList<E> का कार्यान्वयन E[] के बजाय डेटा संग्रहण के लिए सरणी Object[] का उपयोग क्यों करता है? Object[] का उपयोग करने का क्या फायदा है?ArrayList कार्यान्वयन ऑब्जेक्ट [] का उपयोग क्यों करता है?

उत्तर

7

जावा में, सामान्य प्रकार की सरणी बनाना सरल नहीं है।

सरल दृष्टिकोण संकलित करता है नहीं:

public class Container<E> { 

    E[] arr = new E[3]; // ERROR: Cannot create a generic array of E 

} 

Object साथ E बदलें, और सब कुछ ठीक है (कंटेनर को लागू करने में कहीं और जटिलता की कीमत पर)।

वैकल्पिक दृष्टिकोण हैं, लेकिन वे ट्रेडऑफ का एक अलग सेट प्रस्तुत करते हैं। एक व्यापक चर्चा के लिए, (जो है, तथ्य यह है कि इस तरह के अपने उदाहरण में E के रूप में जेनरिक प्रकार पैरामीटर संकलन प्रकार में नष्ट हो जाती हैं), मुझे लगता है उत्पन्न बाईटकोड दोनों ही मामलों में समान होगा How to create a generic array in Java?

+0

आप सही हैं! धन्यवाद!!! – user485553

+3

कोई अभी भी एक अनचेक कास्ट 'ई [] arr = (ई []) नया ऑब्जेक्ट [3];' – Saintali

+1

@ सैंटली: कर सकता है, लेकिन आप उस समय 'क्लासकास्ट अपवाद' प्राप्त करेंगे जब आप काम करने का प्रयास करेंगे यह सरणी कोशिश करो। – NPE

2

type erasure ध्यान में रखते हुए देखते हैं।

किसी रखरखाव बिंदु से, ऑब्जेक्ट के बजाय एक प्रकार पैरामीटर का उपयोग करने से कोड को पढ़ने में आसान हो जाएगा (क्योंकि यह सीमित होगा)। लेकिन ArrayList के एपीआई ने कभी भी "कच्चे" Object सरणी का खुलासा नहीं किया है, मुझे लगता है कि यह केवल जावा डेवलपर्स के लिए कोई फर्क नहीं पड़ता :)

4

तो सबसे पहले, एहसास करें कि सरणी ऑब्जेक्ट का वास्तविक रनटाइम प्रकार होना चाहिए Object[] हो। ऐसा इसलिए है क्योंकि सरणी रनटाइम पर उनके घटक प्रकारों को जानते हैं (विभिन्न सरणी प्रकार वास्तव में रनटाइम पर अलग-अलग प्रकार हैं), और इस प्रकार आपको सरणी बनाने में घटक प्रकार निर्दिष्ट करने की आवश्यकता है, लेकिन ArrayList ऑब्जेक्ट रनटाइम पर इसके प्रकार के तर्क को नहीं जानता है।

जिसके अनुसार, उदाहरण चर के संकलन समय प्रकार या तो Object[] या E[] के रूप में, अलग-अलग फायदे और नुकसान के साथ घोषित किया जा सकता:

यह Object[] के रूप में घोषित किया गया है:

private Object[] arr; 
// to create it: 
arr = new Object[3]; 
// to get an element: 
E get(int i) { return (E)arr[i]; } 

इसका नुकसान यह है कि जब भी आप इसे से बाहर लेते हैं, तो आपको इसे E पर डालना होगा, जिसका अर्थ है कि आप मूल रूप से इसे प्री-जेनेरिक कंटेनर के रूप में उपयोग कर रहे हैं।

यह घोषित किया जाता है, तो के रूप में E[]:

private E[] arr; 
// to create it: 
arr = (E[])new Object[3]; 
// to get an element: 
E get(int i) { return arr[i]; } 

इसका लाभ तुम अब जब आप इसे से बाहर बातें कास्ट करने के लिए है कि है - यह प्रकार की जाँच arr के उपयोग पर प्रदान करता है, जेनेरिक कंटेनर की तरह। नुकसान यह है कि, तार्किक रूप से, कास्ट झूठ बोल रहा है - हम जानते हैं कि हमने एक ऑब्जेक्ट बनाया है जिसका रनटाइम प्रकार Object[] है, और इसलिए यह E[] का उदाहरण नहीं है, जब तक EObject नहीं है।

हालांकि, ऐसा करने में कोई तत्काल समस्या नहीं है, क्योंकि E कक्षा के उदाहरण विधियों के अंदर Object पर मिटा दिया गया है।समस्या का एकमात्र तरीका यह हो सकता है कि यदि ऑब्जेक्ट किसी भी तरह से कक्षा के बाहर (उदाहरण के लिए एक विधि में लौटाया गया है, सार्वजनिक क्षेत्र में डाला गया है) एक क्षमता में है जो E[] (जो यह नहीं है) के रूप में इसका उपयोग करता है :

// This would be bad. It would cause a class cast exception at the call site 
E[] getArray() { return arr; } 

लेकिन ArrayList, और वास्तव में किसी भी ठीक से से डिजाइन कंटेनर वर्ग, इस तरह के बाहर करने के लिए अपने आंतरिक सरणी के रूप में एक कार्यान्वयन विस्तार का पर्दाफाश कभी नहीं होगा। यह अन्य चीजों के साथ, अमूर्त तोड़ देगा। इसलिए जब तक इस वर्ग के लेखक को इस सरणी को उजागर करने के बारे में पता नहीं है, इस तरह से ऐसा करने में कोई समस्या नहीं है (शायद उस व्यक्ति को भ्रमित करने वाले को बचाएं जो कोड देखता है और इससे अनजान है), और लेने के लिए स्वतंत्र है बढ़ी हुई टाइप-चेकिंग का लाभ जो इस तरह लाता है।

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