2011-09-02 12 views
5

मैं एक विधि का उपयोग करता है varargs सुविधा हैमैं एक सूची की सामग्री को एक varargs विधि में कैसे पास कर सकता हूं?

void add(Animal ...); 

अब, बजाय .add(dog, cat) करने का, मैं तत्वों की अज्ञात संख्या के साथ एक पशु सूची है,

List<Animal> i = new ArrayList<Animal>(); 
i.add(dog); 
i.add(cat); 

और साथ जोड़ने के कॉल करना चाहते हैं इस सूची के तत्व।

मुझे लगता है कि मैं एक सरणी का उपयोग कर सकता हूं, लेकिन जब मैं .add(i.toArray()) करता हूं, तो यह एक कंपाइलर त्रुटि देता है।

ऐसा करने का सही तरीका क्या है?

+0

मैं सवाल नहीं समझ सकता। आपने अपना खुद का तरीका'add (Animal ...) 'बनाया है लेकिन आप ArrayList.add (ऑब्जेक्ट) को कॉल कर रहे हैं और स्वयं नहीं। ऐसा क्यों है? कृपया कोड के संदर्भ के साथ प्रश्न संपादित करें। क्या आपके'add 'विधि के अंदर कोड का ब्लॉक है? यदि आपकी एकमात्र समस्या यह है कि आप ऑब्जेक्ट [] को पशु [] पर नहीं डाल सकते हैं तो] @Tom उत्तर का पालन करें। – aalku

+0

भविष्य के लिए बस एक नोट: यदि आपके पास एक कंपाइलर त्रुटि है, तो कृपया इस त्रुटि के लिए पूर्ण त्रुटि संदेश और स्रोत कोड लाइनों की प्रतिलिपि बनाएँ। –

उत्तर

10

यह है:

add(i.toArray(new Animal[i.size()])) 

List.toArray रिटर्न एक Object[], सूची प्रकार तर्क की परवाह किए बिना: भले ही आप new List<String>().toArray() लिख सकते हैं, तो आप एक Object[] मिल जाएगा। हालांकि, version of toArray that takes an array to fill रिटर्न सही प्रकार के साथ एक सरणी: यदि आप new List<String>().toArray(new String[0]) लिखते हैं, आप एक String[] मिल जाएगा। ध्यान दें कि आपके द्वारा पास किए गए सरणी का आकार भी सूची के आकार से मेल नहीं खाता है, हालांकि यह सुनिश्चित करने के लिए अच्छा अभ्यास है कि यह करता है।

यह अंततः जेनेरिक की हल्की मुश्किल विशेषता के कारण है। पहली नज़र में, आपको लगता है हो सकता है कि String[] और List<String> अपने आधार प्रकार के लिए इसी तरह की बातों का मतलब है - एक तार की एक सरणी है, अन्य स्ट्रिंग की एक सूची है।

हालांकि, वे वास्तव में बहुत अलग हैं।

एक सरणी एक भाषा आदिम है, और इसका प्रकार इसमें बेक है। यदि आप एक हेक्स संपादक लिया और JVM में स्मृति में एक सरणी उदाहरण को देखा, तो आप को खोजने के लिए सक्षम हो जाएगा (कहीं आस-पास) जाने वाली वस्तुओं को धारण के प्रकार के रिकार्ड। इसका मतलब है कि यदि आप किसी अज्ञात घटक प्रकार की एक सरणी का एक उदाहरण लेते हैं, आप कर सकते हैं find out what that type is। इसके विपरीत, यह है कि आप create an instance of an array के लिए जा रहे हैं, तो आप को पता है कि घटक प्रकार आप चाहते हैं की जरूरत का मतलब है।

List, दूसरे हाथ पर, जेनरिक, जो जावा में type erasure साथ कार्यान्वित किया जाता है का उपयोग करता है, जिसका अर्थ है कि मोटे तौर पर कहा जाए तो यह कुछ है कि संकलक में मौजूद है, लेकिन रन टाइम पर नहीं (संकलक जांच कर सकते हैं कि आप इसे सही समझें, लेकिन जेवीएम नहीं कर सकता)। यह एक सरल और कुशल कार्यान्वयन की ओर जाता है (एक काफी सरल JVM बदले बिना पूर्व जेनरिक जावा में जोड़ा गया है करने के लिए), लेकिन यह कुछ कमियों है - विशेष रूप से, जो रनटाइम के दौरान, वहाँ कोई रास्ता नहीं है कि किस प्रकार तर्क बताने के लिए है जेनेरिक क्लास के किसी भी विशेष उदाहरण पर, क्योंकि टाइप तर्क केवल कंपाइलर में मौजूद हैं। क्योंकि toArray() को संभालने के लिए यह List उदाहरण पर है, केवल एक चीज जो यह कर सकती है वह Object[] बना सकती है। यह सिर्फ उपयोग करने के लिए एक और विशिष्ट प्रकार के बारे में पता नहीं है।इस को देखने का

एक तरह से, कि सरणियों, उनके वर्ग के हिस्से के रूप में एक प्रकार तर्क है, जबकि List उनके प्रकार के हिस्से के रूप में एक प्रकार तर्क है, और के बाद से वस्तुओं वर्गों है, लेकिन चर प्रकार है आप किसी ऑब्जेक्ट से List का प्रकार तर्क प्राप्त नहीं कर सकते हैं, केवल एक ऑब्जेक्ट को रखने वाले चर से (एक तरफ के रूप में, आप एक सरणी वाले चर से एक सरणी के प्रकार तर्क भी प्राप्त नहीं कर सकते हैं (Object[] array = new String[0]; पर विचार करें) लेकिन यह वास्तव में कोई फर्क नहीं पड़ता क्योंकि, परिवर्तनीय आपको ऑब्जेक्ट को पकड़ने देता है - जब तक कि यह शून्य न हो)।

कोड को यह नीचे उबाल करने के लिए, समस्या है:

public <E> E[] createSimilarlyTypedArray(List<E> list) { 
    Class<E> componentType = list.???; // there is no way to do this 
    return Arrays.newInstance(componentType, list.size()); 
} 
+0

यह आपके सरणी का उपयोग करेगा यदि यह काफी बड़ा है या यदि यह नहीं है तो एक नया आवंटित करें। – aalku

+0

आपको एक टाइपकास्ट अपवाद नहीं मिलेगा जब आप i.toArray (new Animal []) को उस सूची पर कॉल करते हैं जिसमें सामान्य प्रकार सेट नहीं होता है? –

+1

@ बेंजामिन: नहीं, आप नहीं करेंगे। 'Arrays चलाने का प्रयास करें। asList ("हैलो")। ToArray (नया स्ट्रिंग [1]); '- यह पूरी तरह से काम करता है। सांख्यिकीय रूप से, यह ठीक है क्योंकि 'toArray' का वह संस्करण इसके पैरामीटर से अपने पैरामीटर को ऊपर उठाता है, न कि' सूची '(अजीब लेकिन सही!) के स्वामित्व में, और गतिशील रूप से, यह ठीक है क्योंकि रनटाइम पर,' सूची' प्रकार मिटा दिया गया है –

0

जब मैं .add (i.toArray()) यह एक त्रुटि देता है करते हैं, उचित तरीके से यह करने के लिए क्या है ?

foo.addAll(i) का उपयोग करें और फिर आवश्यकता होने पर foo को सरणी में कनवर्ट करें।

0

आपकी विधि void add(Animal...)Animal कक्षा या पशु वस्तुओं के साथ एक सरणी की एक वस्तु की अपेक्षा करता है। आप इसे Object कक्षा की वस्तुओं के साथ एक सरणी देते हैं।

List<Animal> animals = new ArrayList<Animal>(); 
animals.add(dog); 
animals.add(cat) 

तब तर्क के रूप में सूची, जबकि यह एक सरणी में कनवर्ट करने के लिए, अपने विधि के लिए इतना तरह पार्स:

add(animals.toArray(new Animal[animals.size()]); 

अधिक जेनरिक पर में पाया जा सकता सूची इसलिए जैसा एक आम प्रकार दें जावा एपीआई

http://download.oracle.com/javase/1,5.0/docs/guide/language/generics.html

+1

"इसमें 'पशु' वस्तुओं के साथ एक सरणी की अपेक्षा से अधिक", यह एक सरणी की अपेक्षा करता है जिसका अपना प्रकार 'पशु [] 'है। 'ToArray' का शून्य-तर्क रूप' इसमें 'Animal' ऑब्जेक्ट्स वाला सरणी बनाता है - एक सरणी जो मूल रूप से' नया ऑब्जेक्ट [] {नया पशु()} 'है। हालांकि, क्या आवश्यक है 'नया पशु [] {नया पशु()} '। सरणी और जेनेरिक के बीच संगम पानी का वास्तव में विश्वासघाती पैच है! –

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

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