2009-04-14 6 views
45

मैं कक्षाओं की एक सरणी बनाना चाहता हूं, प्रत्येक एक ऐसे प्रकार का प्रतिनिधित्व करता है जो उस प्रणाली में उपलब्ध है जो मैं बना रहा हूं। शामिल सभी वर्ग एक सामान्य सुपरक्लास के उप-वर्ग हैं। तो मैं क्या करना चाहते हैं:मैं कक्षाओं की सरणी के साथ जेनेरिक का उपयोग कैसे करूं?

Class<? extends SuperClass>[] availableTypes = { SubClass1.class, SubClass2.class }; 

यह मैं त्रुटि देता है:

Cannot create a generic array of Class<? extends SuperClass>. 

मैं एक ही संदेश मिलता है कि अगर मैं के दाहिने हाथ की ओर सरणी के निर्माण के अर्हता प्राप्त करने की कोशिश प्रारंभ:

:

Class<? extends SuperClass>[] availableTypes = Class<? extends SuperClass>[] { SubClass1.class, SubClass2.class }; 

मैं अगर मैं जेनरिक योग्यता को खत्म संकलित करने के लिए कोड प्राप्त कर सकते हैं 210

लेकिन फिर मुझे जेनेरिक चेतावनी मिलती है:

कक्षा एक कच्ची प्रकार है। सामान्य प्रकार वर्ग के संदर्भ पैरामीटरकृत किया जाना चाहिए।

मैं कोशिश कर रहा हूं; मैं कोशिश कर रहा हूँ! :) इसके अलावा, इस बिंदु पर, भले ही इससे कोई चेतावनी न उठी, मैं इंटरफ़ेस का एक टुकड़ा खो देता हूं जिसे मैं परिभाषित करने की कोशिश कर रहा था। मैं सिर्फ मनमाने ढंग से कक्षाओं की एक सरणी वापस नहीं करना चाहता; मैं कक्षाओं की एक सरणी वापस करना चाहता हूं जो किसी विशेष सुपर क्लास के सभी उप-वर्ग हैं!

ग्रहण में जेनिक्स घोषणाओं को ठीक करने के लिए किस पैरामीटर का उपयोग करना है, यह जानने के लिए ग्रहण में कुछ सुंदर शक्तिशाली उपकरण हैं, लेकिन इस मामले में यह गिरता है, क्योंकि जब आप कक्षा से निपटते हैं तो यह घटता है। यह "इन्फर जेनेरिक टाइप तर्क" प्रक्रिया प्रदान करता है, चेतावनी छोड़कर, कोड को बिल्कुल भी नहीं बदलता है।

मैं बजाय एक संग्रह का उपयोग करके इस को हल करने के करने में सक्षम था:

List<Class<? extends SuperClass>> availableTypes = new List<Class<? extends SuperClass>>(); 

लेकिन क्या सरणियों के साथ यह करने के लिए सही तरीका है?

उत्तर

22

यह थोड़ा परास्नातक लगता है, लेकिन इस तरह की समस्याएं यही कारण है कि ज्यादातर लोग मिश्रित सरणी और जेनेरिक मिश्रण से बचते हैं। जिस तरह से जेनेरिक लागू किए जाते हैं (type erasure), सरणी और जेनेरिक कभी भी अच्छी तरह से काम नहीं करेंगे।

दो समाधान: एक संग्रह (जैसे ArrayList<Class<? extends SuperClass>>) है, जो काम करता है बस के रूप में अच्छी तरह से एक सरणी का उपयोग करने के

  • स्टिक और भी विस्तार की अनुमति देता है।
  • एक प्रयोग के साथ सरणी बनाने वाले कोड पर @SuppressWarnings("unchecked") एनोटेशन डालें, इसके उपयोग को उचित ठहराने के साथ।
2

समस्या यह है कि एक सामान्य प्रकार की सरणी बनाना अवैध है। जब आप सरणी बनाते हैं तो इसके आसपास जाने का एकमात्र तरीका जेनेरिक प्रकार को कास्ट करना है, लेकिन यह एक बहुत अच्छा समाधान नहीं है। (ध्यान दें कि यह उपयोग एक सामान्य सरणी के लिए संभव है, सिर्फ एक का निर्माण नहीं:। this question देखें)

आप लगभग हमेशा वैसे भी सरणियों के बजाय सूचियों का उपयोग किया जाना चाहिए, तो मैं आप पहले से ही सबसे अच्छा समाधान के साथ आया लगता है ।

14

उपयोग इस वाक्य:

Class<? extends SuperClass>[] avail = new Class[] { SubClass1.class, ... }; 

यह आप एक प्रकार है कि सरणी में SuperClass विस्तार नहीं करता है के लिए एक Class वस्तु सहित किया जा सकता है के बाद से, एक "अनियंत्रित" चेतावनी आप दे देंगे, और सही भी।

11

सरणी के साथ ऐसा करने का सही तरीका संग्रह के साथ करना है। माफ़ कीजिये! कारणों के एक जटिल सेट के लिए, जेन जेनिक्स के साथ अच्छा नहीं खेलते हैं। सामान्य वस्तुओं की तुलना में Arrays के पास एक अलग कॉन्वर्सिस मॉडल होता है, जो अंततः उन समस्याओं का कारण बनता है जिनमें आप चल रहे हैं। उदाहरण के लिए, सरणियों के साथ नहीं, बल्कि (सामान्य रूप से) सामान्य वस्तुओं के साथ, आप कानूनी तौर पर ऐसा कर सकते हैं:

Object[] myArray = new String[5]; 

जबकि यदि आप ऐसा नहीं कर सकते हैं:

LinkedList<Object> myCollection = new LinkedList<String>(); 

आप और अधिक विस्तार चाहते हैं, आप देख सकते हैं उत्कृष्ट Generics FAQ

रूप simonn कहा से Arrays In Java Generics पेज, आप भी सिर्फ अपने सरणियों का उपयोग के रूप में वे कर रहे हैं, और @SuppressWarnings("unchecked") का उपयोग चेतावनी मौन कर सकते हैं। यह काम करेगा, लेकिन बिना किसी सुरक्षा के जेनरिक आपको प्रदान कर सकता है। यदि यह प्रदर्शन है जिसके बारे में आप चिंतित हैं, तो बस ArrayList का उपयोग करें ताकि आप सरणी के चारों ओर एक पतली रैपर का उपयोग कर रहे हों, लेकिन जेनरिक द्वारा प्रदान की जाने वाली सभी प्रकार की सुरक्षा गारंटी के साथ।

+1

सहप्रसरण! आपने बुरा शब्द कहा! –

4

But what's the right way to do this with arrays?

ऐसा करने के लिए कोई प्रकार का सुरक्षित तरीका नहीं है; संग्रह का उपयोग कर सही दृष्टिकोण है। यह देखने के लिए क्यों, कल्पना कीजिए कि इसकी अनुमति है या नहीं। आप इस तरह एक स्थिति हो सकता है:

// Illegal! 
Object[] baskets = new FruitBasket<? extends Citrus>[10]; 

// This is okay. 
baskets[0] = new FruitBasket<Lemon>(); 

// Danger! This should fail, but the type system will let it through. 
baskets[0] = new FruitBasket<Potato>(); 

प्रकार प्रणाली का पता लगाने के एक टोकरी सरणी में जोड़ दी जाती है कि प्रकार FruitBasket<? extends Citrus> या एक उप प्रकार का है कि क्या जरूरत है। एक FruitBasket मेल नहीं खाता है और ArrayStoreException के साथ खारिज कर दिया जाना चाहिए। लेकिन कुछ भी नहीं होता!

टाइप एरर के कारण, JVM केवल सरणी के रनटाइम प्रकार को देख सकता है। रनटाइम पर, हमें यह सुनिश्चित करने के लिए कि वे मेल खाते हैं, सरणी प्रकार को तत्व प्रकार से तुलना करने की आवश्यकता है। सरणी के रनटाइम घटक प्रकार टाइप एरर के बाद FruitBasket[] है; इसी तरह, तत्व का रनटाइम प्रकार FruitBasket है। कोई समस्या नहीं मिलेगी - और यही कारण है कि यह खतरनाक है।

0

टाइप नहीं सुरक्षित और अनियंत्रित डाली चेतावनी के साथ:

Class<? extends SuperClass>[] availableTypes = 
    (Class<? extends SuperClass>[]) 
    (new Class[]{ SubClass1.class, SubClass2.class }); 
संबंधित मुद्दे