2012-04-14 22 views
5

मैंने q1, q2, q3 पर प्रश्नों पर एक नज़र डाली, लेकिन वे बिल्कुल मेरे प्रश्न को कवर नहीं करते हैं।"ArrayList <A>" और "ArrayList <? extends A>" के बीच व्यावहारिक अंतर क्या है?

ध्यान दें कि ArrayList<A> and ArrayList<? extends A> का उपयोग चर या पैरामीटर घोषित करने के लिए किया जाना चाहिए (एक नई जेनेरिक कक्षा बनाने के लिए नहीं)।

दोनों भाव बराबर जब एक वस्तु विशेषता की घोषणा (मामले 1) ?: हैं

class Foo { 

    private ArrayList<A> aList; // == ArrayList<? extends A> aList; 
} 

संपादित करें: दोनों भाव क्या वस्तुओं की तरह aList में जोड़े जाने की अनुमति दी जाती है की दृष्टि से बराबर कर रहे हैं ?, लेकिन अलग-अलग निम्न मामले के समान अर्थ में?

लेकिन वे अलग है जब एक पैरामीटर घोषणा (मामले 2) ?:

void methodFoo(ArrayList<A> al) != void methodFoo(ArrayList<? extends A> al) 

में प्रयोग किया जाता है, क्योंकि पहले एक ही इजाजत दी पारित होने के लिए ArrayList वस्तुओं जबकि दूसरे की तरह "और अधिक अनुमोदक" होगा की अनुमति देता है ArrayList<A1> और ArrayList<A2> (जब तक ए 1 और ए 2 विस्तारित ए) भेजा जाए?

यदि यह सही है, तो क्या कोई अन्य परिदृश्य है जहां दो अभिव्यक्ति प्रभावी ढंग से भिन्न हैं?

धन्यवाद,

+0

जहां तक ​​मुझे पता है, कोई अंतर नहीं है। –

उत्तर

8

चलिए कुछ व्यावहारिक उदाहरण देखें। कहो, तुम हो:

List<Number> list; 

इसका मतलब यह है कि जो कुछ भी इस चर को सौंपा गया है या तो आपको हमेशा पता है क्या उम्मीद करने के लिए क्षेत्र Number और आउटपुट Number लेता है,। Integer को इस सूची में जोड़ा जा सकता है क्योंकि IntegerNumber फैलाता है।हालांकि, आप इस सूची में ArrayList<Long> असाइन नहीं कर सकते हैं।

लेकिन इस मामले पर विचार करें:

List<? extends Number> list; 

यह एक का कहना है: हे, कि कुछ है कि Number फैली की एक सूची है, लेकिन कोई भी exacty क्या जानता है। इसका क्या मतलब है? इसका अर्थ यह है कि आप इस सूची में ArrayList<Long> निर्दिष्ट कर सकते हैं, जिसे आप पहले मामले में नहीं कर सके। आप अभी भी जानते हैं कि जो कुछ भी इस सूची आउटपुटNumber होगा, लेकिन आप Integer में अब Integer डाल सकते हैं।

वहाँ भी एक विपरीत मामला है:

List<? super Number> list; 

मुद्रण तक कि आप कहते हैं: कि Number या उसके सुपर-क्लास की एक सूची है। यह वह जगह है जहां सब कुछ विपरीत हो जाता है। सूची अब ArrayList<Object> और ArrayList<Number> का संदर्भ दे सकती है। अब हम नहीं जानते कि यह सूची आउटपुट क्या होगी। क्या यह Number होगा? क्या यह Object होगा? लेकिन अब हम जानते हैं कि हम Number इस सूची में Number जैसे Integer या Long पर किसी भी उप-वर्ग को डाल सकते हैं।

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

मुझे आशा है कि इससे मामलों को मंजूरी मिल जाएगी।

+0

@ माल्कॉम: 'सूची' में किस प्रकार की चीजें हो सकती हैं या नहीं, इस बारे में अच्छी व्याख्या। केस 2 के बारे में क्या: एक विधि किस प्रकार की सूचियों को स्वीकार कर सकती है? – cibercitizen1

+0

@ cibercitizen1 जैसा कि मैंने उत्तर में कहा था, 'संख्या' को विस्तारित करने वाली किसी चीज की सूचियां। यह 'सूची ' या 'सूची ' जैसी कुछ हो सकती है। इसलिए आप जानते हैं कि यह सूची आपको 'नंबर' देगी, लेकिन आप नहीं जानते कि आप इसमें क्या डाल सकते हैं। – Malcolm

1

ArrayList<A> एक विशिष्ट वर्ग ए, जहां ArrayList<? extends A> के रूप में वर्ग एक या किसी भी वर्ग है जो एक (ए की उप वर्ग) extands यह अधिक सामान्य

1

एक चर घोषणा के रूप में private ArrayList<A> aList; का उपयोग कर का मतलब है इसका मतलब है वाइल्डकार्ड private ArrayList<? extends A> aList;

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

एफवाईआई: आपको अपने चर/पैरामीटर जैसे List<A> या Collection<A> घोषित करने के लिए एक अधिक अमूर्त प्रकार का उपयोग करना चाहिए। जैसा कि आप देख

public class GenericsTest { 
    private ArrayList<A> la; 
    private ArrayList<? extends A> lexta; 

    void doListA(ArrayList<A> la) {} 
    void doListExtA(ArrayList<? extends A> lexta) {} 

    void tester() { 
    la = new ArrayList<SubA>(); // Compiler error: Type mismatch 
    doListA(new ArrayList<SubA>()); // Compiler error: Type mismatch 
    lexta = new ArrayList<SubA>(); 
    doListExtA(new ArrayList<SubA>()); 
    } 

    static class A {} 
    static class SubA extends A {} 
} 

, एक विधि बुला और बताए एक चर/उदाहरण क्षेत्र में एक ही नियम है:

+0

कि उनके प्रश्न का उत्तर नहीं है। वह पूछ रहा है कि उनके अभिव्यक्ति उदाहरण में ये अभिव्यक्ति अलग-अलग हैं। – Shehzad

+0

ठीक है, तो quesion कुछ हद तक अस्पष्ट है (मेरे लिए)। वैसे भी, ऐसा लगता है कि cibercitizen1 यह धारणा कर रहा है कि ArrayList और ArrayList समकक्ष हैं। और यह सच नहीं है। – nansen

4

यह अंतर की व्याख्या करेगा। अपने घोषित पैरामीटर पर आपके तर्क के असाइनमेंट के रूप में विधि कॉल को देखें।

0

यह पहली बार समझ मुश्किल है, लेकिन विरासत जेनरिक, यानी साथ लागू नहीं करता है तो बी ए फैली हुई है, List<B> नहीं एक "उपवर्ग" की List<A> (करने के लिए आवंटित नहीं किया जा सकता है)। इसके अलावा, List<? extends A>List<A> का "सबक्लास" (असाइन नहीं किया जा सकता) नहीं है।

+1

हां, ऐसा करता है, दोनों विधियों को अपवाद से निपटना होगा। यदि आपके पास '' सूची है, तो इसका मतलब यह नहीं है कि आप इसमें 'बी' नहीं डाल सकते हैं। – Malcolm

+0

हम्मम्म - आप वहीं हैं। मैंने अपमानजनक पाठ को ज़ेड किया है – Bohemian

0

मुख्य अंतर यह है कि यदि सामान्य रूप को बेस क्लास (या इंटरफ़ेस) में किसी विधि में तर्क या वापसी प्रकार के रूप में उपयोग किया जाता है, तो यह ओवरलोडिंग के बजाय ओवरराइडिंग के रूप में गिनने के लिए अधिक प्रकार के हस्ताक्षरों की गणना करने की अनुमति देता है।

Function override-overload in Java

उदाहरण के लिए, निम्नलिखित कोड (जावा 7 में) कानूनी है:

interface A 
{ 
    List<? extends Number> getSomeNumbers(); 
} 

class B implements A 
{ 
    @Override 
    public ArrayList<Integer> getSomeNumbers() 
    { 
     return new ArrayList<>(); 
    } 
} 

Difference between Enumeration<? extends ZipEntry> and Enumeration<ZipEntry>?

यह सब मतलब यह है कि कभी कभी आप कोड है कि कम डाले आवश्यकता आ लिख सकते हैं जब कोई और इसका उपयोग कर रहा है। जो उन्हें केवल टाइपिंग के बारे में कम नहीं करना चाहिए, बल्कि संभावित असफलताओं को भी खत्म करना चाहिए।

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

http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#FAQ812

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