चूंकि यह एक व्यापक रूप से संदर्भित प्रश्न है, और वर्तमान उत्तर मुख्य रूप से समझाते हैं कि यह काम क्यों नहीं करता है (या हैकी, खतरनाक समाधानों का प्रस्ताव करता है जिन्हें मैं कभी भी उत्पादन कोड में नहीं देखना चाहूंगा), मुझे लगता है कि एक और उत्तर जोड़ना उचित है, दिखा रहा है नुकसान, और एक संभावित समाधान।
सामान्य रूप से काम नहीं करने का कारण पहले से ही अन्य उत्तरों में बताया गया है: रूपांतरण वास्तव में वैध है या नहीं, यह उन वस्तुओं पर निर्भर करता है जो मूल सूची में निहित हैं। जब सूची में ऐसी वस्तुएं होती हैं जिनका प्रकार प्रकार का नहीं होता है TestB
, लेकिन एक अलग उपवर्ग का होता है TestA
, तो कलाकार मान्य नहीं होता है।
बेशक, जाति मान्य हो सकती है। आपको कभी-कभी उन प्रकारों के बारे में जानकारी होती है जो संकलक के लिए उपलब्ध नहीं हैं। इन मामलों में, सूचियों को डालना संभव है, लेकिन सामान्य तौर पर, यह अनुशंसित नहीं है :
एक भी हो सकता है ...
- ... पूरी सूची या
- ... सूची के सभी तत्वों को डाला
पहले दृष्टिकोण के निहितार्थ (जो वर्तमान में स्वीकृत उत्तर से मेल खाते हैं) सूक्ष्म हैं। यह पहली नज़र में ठीक से काम करने के लिए लग सकता है। लेकिन अगर इनपुट सूची में गलत प्रकार हैं, तो एक ClassCastException
कोड में पूरी तरह से अलग स्थान पर फेंक दिया जा सकता है, और यह डिबग करना और यह पता लगाना मुश्किल हो सकता है कि सूची में गलत तत्व कहां फिसल गया। सबसे बुरी समस्या यह है कि किसी को सूची में डाले जाने के बाद अवैध तत्व भी जोड़ सकते हैं , जिससे डिबगिंग और भी मुश्किल हो जाती है।
तरीकों ClassCastExceptions
की Collections#checkedCollection
फैमिली के साथ इन स्पुरियस को डिबग करने की समस्या को दूर किया जा सकता है ।
प्रकार के आधार पर सूची को फ़िल्टर करना
एक से परिवर्तित करने की एक और अधिक प्रकार सुरक्षित तरीका List<Supertype>
एक करने के लिए List<Subtype>
वास्तव में करने के लिए है को फ़िल्टर सूची, और एक नई सूची है कि कुछ प्रकार है कि केवल तत्व शामिल हैं पैदा करते हैं। इस तरह की पद्धति के कार्यान्वयन के लिए स्वतंत्रता की कुछ डिग्री हैं (जैसे null
प्रविष्टियों के उपचार के बारे में ), लेकिन एक संभावित कार्यान्वयन इस तरह दिख सकता है:
/**
* Filter the given list, and create a new list that only contains
* the elements that are (subtypes) of the class c
*
* @param listA The input list
* @param c The class to filter for
* @return The filtered list
*/
private static <T> List<T> filter(List<?> listA, Class<T> c)
{
List<T> listB = new ArrayList<T>();
for (Object a : listA)
{
if (c.isInstance(a))
{
listB.add(c.cast(a));
}
}
return listB;
}
इस विधि का उपयोग मनमाने ढंग से सूचियों को फ़िल्टर करने के लिए किया जा सकता है (न केवल किसी दिए गए उपप्रकार-सुपरटेप रिश्ते के साथ प्रकार पैरामीटर के बारे में), इस उदाहरण में:
// A list of type "List<Number>" that actually
// contains Integer, Double and Float values
List<Number> mixedNumbers =
new ArrayList<Number>(Arrays.asList(12, 3.4, 5.6f, 78));
// Filter the list, and create a list that contains
// only the Integer values:
List<Integer> integers = filter(mixedNumbers, Integer.class);
System.out.println(integers); // Prints [12, 78]