2010-08-04 4 views
7

मुझे लगता है कि शीर्षक यह सब लेकिन व्याख्या करनी चाहिए सिर्फ मामले में ...प्रकार सूची की सूची से स्पष्ट रूप से कास्टिंग करने के जोखिम क्या हैं <? जावा में टाइप <MyObject> की सूची में MyObject> को विस्तारित करता है?

मैं पता है कि जोखिम और कास्टिंग से संबंधित संभावित मुद्दों जावा निम्नलिखित स्निपेट से उत्पन्न हो सकता हैं:

List<? extends MyObject> wildcardList = someAPI.getList(); 
List<MyObject> typedList = (List<MyObject>) wildcardList; 

मेरे विचार ये हैं कि वाइल्डकार्ड सूची में सभी ऑब्जेक्ट्स MyObject (सटीक प्रकार या उप-वर्ग) का एक उदाहरण होना चाहिए और इसलिए जब भी टाइप की गई सूची से वस्तुओं को पुनर्प्राप्त किया जाता है तो क्लासकास्ट अपवाद कभी नहीं होना चाहिए। क्या ये सही है? यदि ऐसा है तो संकलक चेतावनी क्यों उत्पन्न करता है?

उत्तर

2

आप टाइप किए गए लिस्ट से ऑब्जेक्ट्स को पुनर्प्राप्त करने के बारे में सही हैं, यह काम करना चाहिए।

समस्या तब होती है जब आप बाद में टाइप की गई सूची में अधिक ऑब्जेक्ट जोड़ते हैं। उदाहरण के लिए, मायऑब्जेक्ट में दो उप-वर्ग ए और बी हैं, और वाइल्डकार्डलिस्ट टाइप ए के थे, तो आप इसे बी नहीं जोड़ सकते हैं। लेकिन चूंकि टाइप की गई सूची मूल प्रकार MyObject है, यह त्रुटि केवल रनटाइम पर पकड़ी जाएगी।

+0

हां। थॉमस बिल्कुल सही है – Neel

0

यह

List<Object> obj = (List<Object>) new ArrayList<String>(); 

मुझे आशा है कि समस्या से स्पष्ट है के समान है। उपप्रकारों की सूची supertypes की सूची में नहीं डाला जा सकता है।

+0

यह संकलित भी नहीं करता है। लेकिन ओपी क्या कर रहा है संकलित करेगा लेकिन रनटाइम पर असफल हो सकता है। –

+0

हाँ, यह सही है। लेकिन मैं सिर्फ यह दिखाना चाहता था कि कुछ मौलिक रूप से गलत था। – Rahul

7

जब तक आप सूची से वस्तुओं को पुनर्प्राप्त नहीं करते हैं तब तक कोई समस्या नहीं होनी चाहिए। लेकिन यह क्रम अपवाद में परिणाम सकता है यदि आप निम्न कोड की तरह उस पर कुछ अन्य तरीकों आह्वान का प्रदर्शन:

List<ChildClassOne> childClassList = new ArrayList<ChildClassOne>(); 
childClassList.add(childClassOneInstanceOne); 
childClassList.add(childClassOneInstanceTwo); 

List<? extends MyObject> wildcardList = childClasslist; // works fine - imagine that you get this from a method that only returns List<ChildClassOne> 
List<MyObject> typedList = (List<MyObject>) wildcardList; // warning 

typedList.add(childClassTwoInstanceOne); // oops my childClassList now contains a childClassTwo instance 
ChildClassOne a = childClassList.get(2); // ClassCastException - can't cast ChildClassTwo to ChildClassOne 

यह केवल बड़ी समस्या है:

List<Integer> intList = new ArrayList<Integer>(); 
    intList.add(2); 

    List<? extends Number> numList = intList; 
    List<Number> strictNumList = (List<Number>) numList; 
    strictNumList.add(3.5f); 

    int num = intList.get(1); //java.lang.ClassCastException: java.lang.Float cannot be cast to java.lang.Integer 
+1

+1, अच्छा उदाहरण। हालांकि, यह इंगित करने लायक है कि जब तक आप केवल "प्राप्त करें" टाइप टाइप करें ** आपको कास्ट ** की आवश्यकता/लाभ भी नहीं है। * केवल * समय जिसे आप कास्ट करना होगा, वह है यदि आप कुछ "असुरक्षित" करना चाहते हैं (लाइब्रेरी विधियों को कॉल करने के लिए संभावित अपवाद के साथ जो उनके सामान्य पैरामीटर के साथ लचीले नहीं हैं)। –

1

आप की तरह कुछ करने पर विचार करें। लेकिन अगर आप केवल अपनी सूची से पढ़ते हैं तो यह ठीक होना चाहिए।

0

जवाब पहले से ही तैनात करने के अलावा, निम्नलिखित

संकलक एक चेतावनी बैठाना प्रकार से एक तत्व बाद में पहुँचा जा सकता है उत्पन्न करता है पर एक नज़र आपका कोड और वह सामान्य रूप से परिभाषित सामान्य प्रकार नहीं है। रनटाइम पर टाइप जानकारी भी उपलब्ध नहीं है।

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