सूची <ऑब्जेक्ट> को सूची <MyClass> में कैसे डाला जाए


99

यह संकलन नहीं है, किसी भी सुझाव की सराहना की।

 ...
  List<Object> list = getList();
  return (List<Customer>) list;

संकलक का कहना है: डाली नहीं कर सकते List<Object>करने के लिएList<Customer>


जवाबों:


156

आप हमेशा किसी भी प्रकार के किसी भी ऑब्जेक्ट को पहले ऑब्जेक्ट पर अप-कास्टिंग करके डाल सकते हैं। आपके मामले में:

(List<Customer>)(Object)list; 

आपको यकीन होना चाहिए कि रनटाइम में सूची में ग्राहक वस्तुओं के अलावा कुछ नहीं है।

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


8
इसकी भी जरूरत है @SuppressWarnings("unchecked")। ध्यान दें कि आप (List)इसके बजाय ऊपर भी कर सकते हैं (Object)
200_success

36

ऐसा इसलिए है क्योंकि ग्राहक एक वस्तु है, ग्राहकों की सूची वस्तुओं की सूची नहीं है । अगर ऐसा होता, तो आप किसी भी वस्तु को ग्राहकों की सूची में डाल सकते थे।


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

1
@ BrainSlugs83 आपकी ज़रूरत के लिए (सूची <ग्राहक>) (ऑब्जेक्ट) सूची;
मुथु गणपति नाथन

@ LasseV.Karlsen मैं कास्टिंग के बारे में बात नहीं कर रहा हूं, मैं कन्वर्सेशन की बात कर रहा हूं। यह प्रकार की सुरक्षा को दरकिनार नहीं करेगा, यह इसे लागू करेगा। जावा का जेनरिक कार्यान्वयन, ऑपरेटर ओवरलोड की कमी, विस्तार के तरीके, और कई अन्य आधुनिक सुविधाओं ने मुझे समय-समय पर निराश किया है। - इस बीच, .NET के पास इसके लिए दो अलग-अलग एक्सटेंशन मेथड हैं - एक कॉल .Cast<T>()और एक कॉल .OfType<T>()। पूर्व प्रत्येक तत्व पर एक कलाकार करता है (वांछित अपवादों को फेंकते हुए), जबकि बाद वाले तत्वों को फ़िल्टर नहीं किया जा सकता है (इसलिए आप अपने उपयोग परिदृश्य के आधार पर एक को चुनेंगे)।
BrainSlugs83

1
@EAGER_STUDENT मैं इसे जावा के पिछले हिस्से में नहीं डालूंगा जो कि वास्तव में काम कर सकता है (यह सब हास्यास्पद प्रकार का व्यवसाय है, मुझे इसे आज़माना होगा ...) - लेकिन नहीं, मैं कभी भी ऐसा कोड नहीं लिखूंगा - आप खो देते हैं प्रकार सुरक्षा, यदि संग्रह का एक तत्व instanceofग्राहक नहीं है तो क्या होगा ?
BrainSlugs83

1
@ BrainSlugs83 वह व्यक्ति जिसने विशेष रूप से कास्टिंग के बारे में पूछा गया प्रश्न पूछा था। और यदि जावा में पहले से ही आपके द्वारा संदर्भित .NET विधियों जैसे प्रासंगिक तरीके नहीं हैं (जो अभी भी btw परिवर्तित नहीं कर रहा है), तो आपको आसानी से उन्हें जोड़ने में सक्षम होना चाहिए। हालांकि यह प्रश्न के लिए सभी थोथा ऑर्थोगोनल है, जिसने विशिष्ट वाक्यविन्यास के बारे में पूछा।
लास वी। कार्लसन

35

आपके अन्य कोड के आधार पर सर्वश्रेष्ठ उत्तर भिन्न हो सकते हैं। प्रयत्न:

List<? extends Object> list = getList();
return (List<Customer>) list;

या

List list = getList();
return (List<Customer>) list;

लेकिन ध्यान रखें कि ऐसी अनियंत्रित जातियों को करने की अनुशंसा नहीं की जाती है।


3
-1 - यह वास्तव में बुरी आदत है, और जब तक आप "अनियंत्रित" एनोटेशन का उपयोग नहीं करते हैं, तब भी कंपाइलर इसके बारे में शिकायत करेगा
kdgregory

24

जावा 8 धाराओं के साथ :

कभी-कभी जानवर बल कास्टिंग ठीक है:

List<MyClass> mythings = (List<MyClass>) (Object) objects

लेकिन यहाँ एक और अधिक बहुमुखी समाधान है:

List<Object> objects = Arrays.asList("String1", "String2");

List<String> strings = objects.stream()
                       .map(element->(String) element)
                       .collect(Collectors.toList());

लाभ का एक टन है, लेकिन एक यह है कि आप अपनी सूची को और अधिक सुरुचिपूर्ण ढंग से रख सकते हैं यदि आप सुनिश्चित नहीं कर सकते हैं कि इसमें क्या शामिल है:

objects.stream()
    .filter(element->element instanceof String)
    .map(element->(String)element)
    .collect(Collectors.toList());

1
यह एक कास्ट की तुलना में अधिक है, हालांकि।
200_सेकंड

स्वीकार किए गए एज़र में उल्लेखित कास्टिंग मेरे लिए काम नहीं करती थी। इसके अलावा मैं जावा 7 पर था। लेकिन अमरूद FluentIterableने मेरे लिए काम किया।
श्रीधर सरनोबत

यह वही है जो मैं ढूंढ रहा था, मुझे सिर्फ
फ्यूल्ड बाय कॉफी


8

ध्यान दें कि मैं कोई जावा प्रोग्रामर नहीं हूं, लेकिन .NET और C # में, इस सुविधा को कंट्रोवर्सी या कोवरियन कहा जाता है। मैंने अभी तक उन चीजों में देरी नहीं की है, क्योंकि वे .NET 4.0 में नए हैं, जिसका मैं उपयोग नहीं कर रहा हूं क्योंकि यह केवल बीटा है, इसलिए मुझे नहीं पता कि दोनों में से कौन सी शर्तें आपकी समस्या का वर्णन करती हैं, लेकिन मुझे वर्णन करें इसके साथ तकनीकी समस्या।

मान लेते हैं कि आपको कास्ट करने की अनुमति दी गई थी। ध्यान दें, मैं कास्ट कहता हूं , क्योंकि आपने जो कहा है, लेकिन दो ऑपरेशन हैं जो संभव हो सकते हैं, कास्टिंग और परिवर्तित करना

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

यहाँ उस के साथ समस्या है।

यदि निम्नलिखित की अनुमति दी जाती है तो क्या होगा (ध्यान दें, मैं यह मान रहा हूं कि कलाकारों से पहले, वस्तुओं की सूची में वास्तव में केवल ग्राहक ऑब्जेक्ट होते हैं, अन्यथा कलाकार जावा के इस काल्पनिक संस्करण में भी काम नहीं करेंगे):

List<Object> list = getList();
List<Customer> customers = (List<Customer>)list;
list.Insert(0, new someOtherObjectNotACustomer());
Customer c = customers[0];

इस मामले में, यह एक वस्तु का इलाज करने का प्रयास करेगा, जो ग्राहक के रूप में ग्राहक नहीं है, और आपको एक बिंदु पर रनटाइम त्रुटि मिलेगी, या तो सूची के अंदर, या असाइनमेंट से फॉर्म।

जेनरिक, हालांकि, आपको संग्रह की तरह, सुरक्षित-सुरक्षित डेटा प्रकार देने के लिए माना जाता है, और चूंकि वे 'गारंटीकृत' शब्द को चारों ओर फेंकना पसंद करते हैं, इस तरह की कास्ट, जो समस्याओं का पालन करती हैं, की अनुमति नहीं है।

.NET 4.0 में (मुझे पता है, आपका प्रश्न जावा के बारे में था), यह कुछ बहुत ही विशिष्ट मामलों में अनुमति दी जाएगी , जहां कंपाइलर गारंटी दे सकता है कि आपके द्वारा किए जाने वाले ऑपरेशन सुरक्षित हैं, लेकिन सामान्य अर्थ में, इस प्रकार का कास्ट नहीं होगा अनुमति पाना। वही जावा के लिए है, हालांकि मैं किसी भी योजना के बारे में अनिश्चित हूँ जो जावा भाषा के साथ सह-विरोधाभासी है।

उम्मीद है, मुझसे बेहतर जावा ज्ञान वाला कोई व्यक्ति आपको जावा भविष्य या कार्यान्वयन के बारे में बता सकता है।


3
जावा का भविष्य है ... स्काला। सच में, जावा पर जेनेरिक बोल्ट लगाने वाले आदमी ने एक नई भाषा विकसित की है जो कि जावा के समान अस्पष्ट है लेकिन वास्तव में, वास्तव में प्रकार के साथ कुशल: टाइप हैंडलिंग का एक बहुत गहन और सुसंगत कार्यान्वयन। मुझे लगता है कि कोई नहीं जानता कि कौन सी स्काला सुविधाएँ जावा में वापस आएंगी, और कब।
कार्ल स्मोत्रिकज

कोविर्सियस की एक उत्कृष्ट व्याख्या जो वास्तव में ओपी प्रश्न का उत्तर देती है। बहुत बढ़िया।
केविन डे

कार्ल: मैंने सोचा कि कुछ जावा देव C # बनाने के लिए आगे बढ़े? :) वैसे भी, जावा भविष्य में स्कैला की दिशा में जाने की सबसे अधिक संभावना है, कहते हैं, कुछ कम दृढ़ता से टाइप किया गया है।
एस्को

@ कार्ल - स्काला में एक सूक्ष्म अंतर है कि डिफ़ॉल्ट रूप से सूचियाँ अपरिवर्तनीय हैं। आम तौर पर यो को ग्राहकों की सूची में ऑब्जेक्ट जोड़ने की समस्या नहीं होती है, क्योंकि जब आप ऐसा करते हैं तो आपको वस्तुओं की एक नई सूची मिलती है ।
ब्रायन एग्न्यू

एर ... तकनीकी रूप से यह सही है - लेकिन .NET 4.0 से पहले भी - आप नियमित IEnumerable एक्सटेंशन विधियों ((.Cast <> और .OfType <>) के साथ ऐसा कर सकते हैं - इसलिए यदि गहरे अंत में जाने की कोई आवश्यकता नहीं है। तुम सिर्फ मजबूत टाइप चलना चाहते हो।
BrainSlugs83

7

एक अन्य दृष्टिकोण जावा 8 स्ट्रीम का उपयोग किया जाएगा।

    List<Customer> customer = myObjects.stream()
                                  .filter(Customer.class::isInstance)
                                  .map(Customer.class::cast)
                                  .collect(toList());

1
धन्यवाद, यह समाधान बहुत सुंदर है, विधि संदर्भ का उपयोग कर
थांग

1
कभी नहीं सोचा था कि कोई उस तक
पहुंच

3

आपको सूची में केवल पुनरावृत्त होना चाहिए और सभी वस्तुओं को एक-एक करके डालना चाहिए


3

आप ऐसा कुछ कर सकते हैं

List<Customer> cusList = new ArrayList<Customer>();

for(Object o: list){        
    cusList.add((Customer)o);        
}

return cusList; 

या जावा 8 रास्ता

list.stream().forEach(x->cusList.add((Customer)x))

return cuslist;

2

आप नहीं कर सकते हैं List<Object>और List<Customer>एक ही वंशानुक्रम में नहीं हैं।

आप अपनी List<Customer>क्लास में एक नया कंस्ट्रक्टर जोड़ सकते हैं List<Object>जो लिस्ट में से प्रत्येक के माध्यम Objectसे एक को कास्टिंग कर रहा है Customerऔर इसे अपने कलेक्शन में जोड़ रहा है। ध्यान रखें कि कॉल करने वाले के पास List<Object>कुछ ऐसा नहीं होने पर एक अमान्य कास्ट अपवाद हो सकता है Customer

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


2

आप एक नई सूची बना सकते हैं और उसमें तत्व जोड़ सकते हैं:

उदाहरण के लिए:

List<A> a = getListOfA();
List<Object> newList = new ArrayList<>();
newList.addAll(a);

1

आपकी सबसे अच्छी शर्त यह है कि एक नया बनाएं List<Customer>, इसके माध्यम से पुनरावृत्त करें List<Object>, प्रत्येक आइटम को नई सूची में जोड़ें, और उसे वापस लौटाएं।


1

जैसा कि दूसरों ने बताया है, आप उन्हें तुरंत नहीं डाल सकते, क्योंकि List<Object>यह एक नहीं है List<Customer>। आप क्या कर सकते हैं, उस सूची पर एक दृश्य को परिभाषित करना है जो इन-प्लेस प्रकार की जाँच करता है। Google संग्रह का उपयोग करना :

return Lists.transform(list, new Function<Object, Customer>() {
  public Customer apply(Object from) {
    if (from instanceof Customer) {
      return (Customer)from;
    }
    return null; // or throw an exception, or do something else that makes sense.
  }
});

1

ऊपर Bozho के साथ भी ऐसा ही है। आप इस विधि के माध्यम से यहाँ कुछ काम कर सकते हैं (हालाँकि मैं खुद इसे पसंद नहीं करता हूँ):

public <T> List<T> convert(List list, T t){
    return list;
}

हाँ। यह आपकी सूची को आपके मांग वाले सामान्य प्रकार में डालेगा।

ऊपर दिए गए मामले में, आप कुछ इस तरह से कोड कर सकते हैं:

    List<Object> list = getList();
    return convert(list, new Customer());

मुझे यह समाधान पसंद है। यहां तक ​​कि अगर आपको SuppressWarnings को जोड़ने की आवश्यकता है, तो भी इसे हर असुरक्षित कास्टिंग की तुलना में एक जगह पर जोड़ना बेहतर है।
रॉबसन

1

सूची के साथ आप क्या करना चाहते हैं, इसके आधार पर, आपको इसे किसी को देने की आवश्यकता भी नहीं हो सकती है List<Customer>। यदि आप केवल Customerवस्तुओं को सूची में जोड़ना चाहते हैं , तो आप इसे निम्नानुसार घोषित कर सकते हैं:

...
List<Object> list = getList();
return (List<? super Customer>) list;

यह कानूनी है (ठीक है, न कि केवल कानूनी, लेकिन सही है - सूची "ग्राहक के लिए कुछ सुपरस्क्रिप्ट") है, और यदि आप इसे एक ऐसी विधि में पारित करने जा रहे हैं जो सूची में केवल वस्तुओं को जोड़ रही होगी तो ऊपर इसके लिए सामान्य सीमाएँ पर्याप्त हैं।

दूसरी ओर, यदि आप सूची से वस्तुओं को पुनः प्राप्त करना चाहते हैं और उन्हें ग्राहक के रूप में दृढ़ता से टाइप किया है - तो आप भाग्य से बाहर हैं, और ठीक ही ऐसा है। क्योंकि सूची है List<Object>कि कोई गारंटी नहीं है कि सामग्री ग्राहक हैं, इसलिए आपको पुनर्प्राप्ति पर अपनी कास्टिंग प्रदान करनी होगी। (या वास्तव में, बिल्कुल, दोगुना यकीन है कि सूची में केवल शामिल होगा Customersऔर दूसरे उत्तरों में से किसी एक से डबल-कास्ट का उपयोग करेगा , लेकिन यह महसूस करें कि आप संकलन-प्रकार-सुरक्षा को पूरी तरह से दरकिनार कर रहे हैं, जिसमें आप जेनरिक से प्राप्त करते हैं मामला)।

मोटे तौर पर यह कहना संभव है कि व्यापक संभव जेनेरिक सीमा पर विचार करना हमेशा अच्छा होता है जो एक विधि लिखते समय स्वीकार्य होगी, दोगुना इसलिए यदि यह लाइब्रेरी विधि के रूप में उपयोग होने वाला है। आप केवल एक सूची से पढ़ने के लिए जा रहे हैं, का उपयोग List<? extends T>करने के बजाय List<T>, उदाहरण के लिए - यह अपने कॉल करने देता है ज्यादा तर्क और इसका मतलब है कि वे कम संभावना है कि आप 'के समान परिहार्य मुद्दों में चलाने के लिए कर रहे हैं वे में पारित कर सकते हैं में अधिक गुंजाइश फिर से यहाँ हो रहा है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.