2014-09-05 8 views
10

ArrayList आंतरिक रूप से वस्तु सरणी का उपयोग करता है:ऐरेलिस्ट ऑब्जेक्ट का उपयोग क्यों करता है [] (ई के बजाय []) आंतरिक रूप से?

private transient Object[] elementData; 

और E get(int) विधि में यह ई प्रकार के डाली है।

मेरा प्रश्न है: क्यों ऑरेलिस्टिस्ट वस्तुओं को स्टोर करने के लिए ई [] का उपयोग नहीं करता है?

मैं समझता हूं कि कंपाइलर चलाने के बाद, टाइप-एरर ई [] ऑब्जेक्ट [] में बदल जाएगा, लेकिन फिर भी हर get() कॉल में ई को डालने की आवश्यकता है?

तो उपयोग यह ई [] नीचे इस कोड नहीं आवश्यक है

return (E) elementData[index]; 

उपयोग वस्तु [] के चुनाव प्रदर्शन के लिए है?

टाइप-एरर ई [] ऑब्जेक्ट [] में बदलता है, जावा सामान्य तरीकों से सही प्रकार को वापस करने के लिए आंतरिक रूप से एक कास्ट बनाता है?

संपादित

मुझे बेहतर क्या मेरी संदेह की बात है समझाने के लिए करते हैं: ArrayList उपयोग ई [] के बजाय [] वस्तु, विधि में (int) प्राप्त

तो डाली नहीं है ज़रूरी। यह प्रदर्शन (जाहिर है) में वृद्धि करेगा।

लेकिन, कोई जादू नहीं है, मुझे लगता है कि ई [] जेवीएम का उपयोग ऑब्जेक्ट कास्ट करेगा, क्योंकि टाइप-एरर ऑब्जेक्ट में बदल जाएगा। सही बात?

ps: मेरी खराब अंग्रेजी के लिए खेद है।

+0

आप को लगता है कि 'ई' असली है लग रहे हैं। यह आपकी कल्पना का चित्र न्यूटन है। सरणी की कक्षा उस समय तय की जाती है जब ऐरेलिस्ट सूची को संकलित किया जाता है, जावा फाउंड्री में वापस। –

+0

@ होट्लिक्स "मैं समझता हूं कि कंपाइलर चलाने के बाद, टाइप-एरर ई [] को ऑब्जेक्ट में बदल देगा []" .. "यदि इसका उपयोग ई [] नीचे दिया गया है [यह आवश्यक नहीं है] [कास्ट का उपयोग करने के लिए]" – user2864740

+0

स्रोत कोड शायद ई [] घोषित करने में सुधार किया जा सकता है, लेकिन अंतिम संकलित परिणाम वही होगा। –

उत्तर

8

अद्यतन: इस उत्तर के रास्ते अधिक ध्यान और upvotes से मुझे लगता है कि यह मूल रूप से कॉपी-पेस्ट JDK स्रोत कोड के लिए हकदार हो गया है, इसलिए मैं यह कुछ योग्य में बदल जाने की कोशिश करने के लिए जा रहा हूँ। या सी # शैली जेनरिक -


जावा जेनरिक देखने के लिए और, सच reified, बहु instantiated, सी ++ की तरह महसूस करने के लिए डिज़ाइन कर रहे हैं। इसका मतलब है कि ArrayList<E> जैसे किसी प्रकार के लिए, हम ArrayList<String> की अपेक्षा करते हैं कि E की प्रत्येक घटना String के साथ प्रतिस्थापित हो। दूसरे शब्दों में, यह:

private Object[] elementData = new Object[size]; 

public E get(int i) { 
    return (E) elementData[i]; 
} 

String str = list.get(0); 

इस बनने के लिए चाहिए:

private Object[] elementData = new Object[size]; 

public String get(int i) { 
    return (String) elementData[i]; 
} 

String str = list.get(0); 

अब, जैसा कि आप शायद जानते हैं, कि नहीं वास्तव में वे कैसे काम करते हैं। पिछड़े-संगत कारणों के लिए जो अब हमारे (लंबे) लंबे समय से पीछे हैं, जावा जेनिक्स टाइप एरर के माध्यम से कार्यान्वित किए जाते हैं, जहां E वास्तव में Object के साथ प्रतिस्थापित किया जाता है, और String को पर कोड पर कॉल किया जाता है जहां आवश्यक हो। इसका मतलब है कि कोड वास्तव में कुछ इस तरह हो जाता है:

private Object[] elementData = new Object[size]; 

public Object get(int i) { 
    return elementData[i]; 
} 

String str = (String) list.get(0); 

(E) के कलाकारों गायब हो गया है, और कॉल स्थल पर दोबारा प्रकट हुई। अगर कॉल साइट ने परिणाम को नजरअंदाज कर दिया था, तो कलाकार पूरी तरह से गायब हो गया होगा! यही कारण है कि उसने एक "अनचेक" चेतावनी दी।


अब कल्पना अगर elementData था इसके बजाय प्रकार E[], आप का सुझाव के रूप में। यही है, कोड इस तरह दिखता था:

private E[] elementData = (E[]) new Object[size]; 

public E get(int i) { 
    return elementData[i]; 
} 

String str = list.get(0); 

हम जानते हैं कि यह उपरोक्त के समान उपरोक्त चीज़ में परिवर्तित हो जाता है। लेकिन अगर हम जेनरिक reified था जैसे हम चाहते हैं हमने किया है, यह इस प्रकार दिखाई देगा:

private String[] elementData = (String[]) new Object[size]; 
// ClassCastException: Object[] is not a String[] 

अनिवार्य रूप से हम कुछ कोड है जो रनटाइम के दुर्घटना चाहिए लिखा है, और एकमात्र कारण यह सब पर काम करता है कि जावा के जेनरिक है कार्यान्वयन से बेहतर होने का नाटक करता है। हमने संकलक को झुकाव कोड स्वीकार करने के लिए इसे मनाने के लिए झूठ बोला है।

और यह भंगुर है! हम रनटाइम दुर्घटनाओं से बचने के लिए होते हैं क्योंकि सरणी कक्षा से कभी नहीं निकलती है। लेकिन अगर ऐसा होता है, तो यह ClassCastException एस कठिन-अनुमानित स्थानों में होगा। क्या होगा यदि जावा 9 ने संशोधित जेनेरिक पेश किए? पहला कार्यान्वयन काम करेगा, लेकिन यह तोड़ देगा।

यही कारण है कि अधिकांश उचित जावा कोडिंग सम्मेलनों में अनचेक किए गए जानवरों को टाइप-सही होने की आवश्यकता होती है। (E) elementData[i] टाइप-सही है क्योंकि ArrayList सुनिश्चित करता है कि केवल E एस elementData में संग्रहीत किया जा सकता है। (E[]) new Object[size] कभी भी टाइप-सही नहीं है जब तक कि EObject है।


अन्य लाभ भी हैं। जावा 8 में, elementData क्षेत्र विशेष प्रहरी मूल्यों पर ले जा सकते हैं:

/** 
* Shared empty array instance used for empty instances. 
*/ 
private static final Object[] EMPTY_ELEMENTDATA = {}; 

/** 
* Shared empty array instance used for default sized empty instances. We 
* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when 
* first element is added. 
*/ 
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; 

/** 
* The array buffer into which the elements of the ArrayList are stored. 
* The capacity of the ArrayList is the length of this array buffer. Any 
* empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA 
* will be expanded to DEFAULT_CAPACITY when the first element is added. 
*/ 
transient Object[] elementData; // non-private to simplify nested class access 
+0

मुझे यकीन नहीं है कि इन विशेष संश्लेषित मूल्यों का अस्तित्व * * के लिए कारण है, या * 'तत्व डेटा' घोषित करने का नतीजा 'ऑब्जेक्ट [] 'के रूप में। – Pshemo

+2

@ पश्मो 'स्थिर ई [] 'अवैध है –

+2

वे अभी भी' स्थिर 'फ़ील्ड को' ऑब्जेक्ट [] 'के रूप में छोड़ सकते हैं और असाइनमेंट पर कास्टिंग' ई []' का उदाहरण फ़ील्ड है। –

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