2008-10-22 7 views
27

Best Practices: Always return a ____, never a ____ की भावना में, मुझे अपने आने वाले migration from JDK1.4.2 to JDK5 and more में एक समान प्रश्न का सामना करना पड़ता है। (हाँ, मैं , JDK1.4.2 is EOL! ;-)) जानता हूं।एपीआई जावा 5 और अधिक: क्या मुझे एक सरणी या संग्रह वापस करना चाहिए?

एक संग्रह लौटने कार्यों के लिए

(जो सरल property collections नहीं हैं), मैं हमेशा पसंद करते हैं (JDK1.4.2 में) एक सामान्य सूची के बजाय एक सरणी लौटने, क्योंकि:

  • यह लौटने प्रकार लागू करता है (MyObject[] वस्तुओं की सूची, के बजाय और अधिक प्रकार सुरक्षित एक स्थिर पर - 'संकलन' के रूप में - स्तर)
  • यह पता चलता है एक 'केवल पढ़ने के लिए' लौटे संग्रह करने के लिए चरित्र (यह है एक हाथ जोड़ने के लिए और अधिक जटिल संग्रह को ध्यान दें, भले ही यह सी # में 'केवल पढ़ने के लिए' कीवर्ड के रूप में कठोर न हो)। यह
बेशक

हुए कहा कि यह सरणी के अंदर संदर्भ अभी भी संशोधित किया जा सकता क्योंकि 'अडिग' है के रूप में ही नहीं है ..., मैं हमेशा बना सकता हूँ इस सरणी लौटे (मैं किसी भी संपर्क में न आएं ' आंतरिक 'सरणी)

अब, जेडीके 5 और अधिक में, मैं List<MyObject> का उपयोग कर सकता हूं यदि मैं चाहता हूं।

जावा 5 में कोडिंग करते समय सूची या Collection<MyObject> की बजाय MyObject[] वापस करने का चयन करने के अच्छे कारण क्या हैं?

  • एक को लागू रीड-ओनली लौटे संग्रह पर विशेषता:

    बोनस, यदि Collection<MyObject> प्रयोग किया जाता है, यह संभव है? (add() या remove() संभव)

  • लौटे हुए संग्रह में एक अपरिवर्तनीय पहलू को लागू करता है? (यहां तक ​​कि उस संग्रह के संदर्भ भी संशोधित नहीं किए जा सकते हैं)

पीएस: JavaGenericFAQ में काफी कुछ नहीं था।

उत्तर

34

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

Arrays और जेनेरिक बहुत अच्छी तरह से मिश्रण नहीं करते हैं। इसलिए, यदि आप जेनेरिक का लाभ लेना चाहते हैं, तो आपको आमतौर पर सरणी से बचें।
आईई: आप सामान्य रूप से एक सरणी नहीं बना सकते हैं। उदाहरण के लिए, यदि टी एक सामान्य प्रकार है तो "नया टी [0]" संकलित नहीं होता है। आपको कुछ ऐसा करना होगा "(टी []) नया ऑब्जेक्ट [0]", जो एक अनचेक कास्ट चेतावनी उत्पन्न करता है। इसी कारण से, आप चेतावनी के बिना varargs के साथ सामान्य प्रकार का उपयोग नहीं कर सकते हैं।

Collections.unmodifiableCollection (और इसी तरह के तरीकों) का उपयोग करके, आपको केवल-पढ़ने वाली बाधा मिलती है (जिसे आप किसी सरणी के साथ प्राप्त नहीं कर सकते - आपको सरणी का क्लोन वापस करना होगा)।

आप सदस्यों की अपरिवर्तनीयता लागू नहीं कर सकते हैं, लेकिन फिर आप इसे किसी सरणी के साथ नहीं कर सकते हैं।

+0

धन्यवाद! अभी के लिए +1 (मैं अन्य उत्तरों के लिए थोड़ा इंतजार करूँगा)। आप बता सकते हैं कि मैंने अभी तक जेडीके 6 जावाडोक को गंभीरता से नहीं पढ़ा है ...;) – VonC

+0

"Arrays और जेनरिक बहुत अच्छी तरह से मिश्रण नहीं करते हैं। इसलिए, यदि आप जेनेरिक का लाभ लेना चाहते हैं, तो आपको आमतौर पर सरणी से बचना चाहिए।" -> Urg? क्या आप इस भाग को समझा सकते हैं? मेरे सरणी मेरे जेनेरिक के साथ अच्छी तरह मिलाते हैं ... – Nicolas

+0

आप सामान्य रूप से एक सरणी नहीं बना सकते हैं। उदाहरण के लिए, यदि टी एक सामान्य प्रकार है तो "नया टी [0]" संकलित नहीं होता है। आपको कुछ ऐसा करना होगा "(टी []) नया ऑब्जेक्ट [0]", जो एक अनचेक कास्ट चेतावनी उत्पन्न करता है। इसी कारण से, आप चेतावनी के बिना varargs के साथ सामान्य प्रकार का उपयोग नहीं कर सकते हैं। –

3

Collections कक्षा में अपरिवर्तनीय * विधियों को वापस लौटाए गए संग्रह को केवल पढ़ने योग्य/अपरिवर्तनीय बनाने के लिए देखें। यह मूल संग्रह को उस सूची में लपेट देगा जो सूची को बदलने के लिए पहुंच को रोकता है (तत्व स्वयं हालांकि अपरिवर्तनीय नहीं हैं)। उदाहरण के लिए

unmodifiableList

मेरे लिए यह इस बात पर निर्भर करता है कि लौटाई गई सूची का उपयोग कैसे किया जाएगा। इसे किस अन्य तरीके से पारित किया जा रहा है, और इसका उपयोग कैसे किया जाएगा? आम तौर पर मैं एक सरणी पर जेनेरिक संग्रह पसंद करूंगा, लेकिन मामले के आधार पर इसे किसी मामले में बदल दूंगा।

यदि आप कुछ महत्वपूर्ण कर रहे हैं तो सरणी शायद तेज प्रदर्शन करेगी।

+0

यहां कोई वास्तविक समय प्रक्रिया शामिल नहीं है। और संग्रह "संपत्ति" का प्रतिनिधित्व नहीं करता है, केवल गणना मूल्य। – VonC

2

मेरा उत्तर डाउनवॉटेड था क्योंकि मैं कक्षा के लिए प्रॉक्सी का उपयोग करता हूं और उन चीजों का उपयोग (प्रॉक्सी और प्रतिबिंब) को मना कर दिया जाता है क्योंकि यह कुछ लोगों के दिमाग के प्रदर्शन को प्रभावित करता है (कई लोग प्रतिबिंब का उपयोग भी नहीं करते हैं, हालांकि वे हाइबरनेट का उपयोग करते हैं और वसंत जो रिलेक्शन, कक्षा प्रॉक्सी और एक्सएमएल का उपयोग करते हैं)।

cglib.sourceforge.net प्रोजेक्ट से एन्हांसर, यह कक्षाओं के लिए प्रॉक्सी बनाने की अनुमति देता है (जेडीके इंटरफेस के लिए केवल प्रॉक्सी का समर्थन करता है)। प्रॉक्सी आपको ऑब्जेक्ट में विधियों को नियंत्रित करने की अनुमति देता है, हालांकि आप प्रतिबिंबों का उपयोग करके फ़ील्ड तक नहीं पहुंच सकते हैं। अगर आपके पास कुछ सवाल पूछते हैं।

+0

कोड और परिशुद्धता के लिए धन्यवाद। +1, लेकिन मैं कभी भी अपने कोड में उस तरह की अतिरिक्त परत का उपयोग कभी भी नहीं कर सकता ... – VonC

+0

मैं समझता हूं, लेकिन मैं वास्तव में यह कहना चाहता हूं कि यह संग्रह .unmodifiableCollection का उपयोग करने जैसा है। यह आपको तब तक कुछ नहीं देता जब तक कि आपके संग्रह को आपके द्वारा संशोधित नहीं किया जाता है। –

10

असल में सरणी अभी भी संग्रह/सूचियों पर एक फायदा है। जावा एरर जेनरिक्स को टाइप एरर के माध्यम से लागू करने के कारण, आपके पास दो विधियां नहीं हो सकतीं जो संग्रह के रूप में संग्रह लेती हैं, फिर भी संग्रह के जेनेरिक प्रकार से भिन्न होती हैं।

पूर्व:

public void doSomething(Collection<String> strs) { ... } 
public void doSomething(Collection<Integer> ints) { ... } 

दो उपरोक्त विधियों संकलन नहीं करेगा क्योंकि javac संकलक प्रकार विलोपन का उपयोग करता है और इस तरह JVM के प्रकार की जानकारी पारित नहीं कर सकते हैं। JVM केवल दो विधियों को देखेगा जो संग्रह को इसके तर्क के रूप में लेते हैं।

उपर्युक्त मामलों में, विधियों को उनके तर्कों के रूप में सरणी बनाने और संग्रह/सूची के लिए एर्रे() विधि का उपयोग करने के लिए सबसे अच्छा काम करना है। यदि आप अभी भी उपरोक्त विधियों के अंदर संग्रह/सूची का उपयोग करना चाहते हैं, तो अपनी सूची वापस पाने के लिए बस java.util.Arrays.asList() विधि का उपयोग करें।

पूर्व:

public void doSomething(String[] strs) { 
     List<String> strList = Arrays.asList(strs); 
     ... 
} 

public void doSomething(Integer[] ints) { 
     List<Integer> intList = Arrays.asList(ints); 
     ... 
} 

public static void main(String[] args) { 
     List<String> strs = new ArrayList<String>(); 
     List<Integer> ints = new ArrayList<Integer>(); 
     obj.doSomething(strs.toArray()); 
     obj.doSomething(ints.toArray()); 
} 
+1

उत्कृष्ट बिंदु। उसे इंगित करने के लिए धन्यवाद। – VonC

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

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