मैं कैसे ठीक करूँ "प्रकार सूची की अभिव्यक्ति को अनियंत्रित रूपांतरण की आवश्यकता है ... '?


137

जावा स्निपेट में:

SyndFeedInput fr = new SyndFeedInput();
SyndFeed sf = fr.build(new XmlReader(myInputStream));
List<SyndEntry> entries = sf.getEntries();

अंतिम पंक्ति चेतावनी उत्पन्न करती है

"प्रकार की अभिव्यक्ति के Listअनुरूप अनियंत्रित रूपांतरण की आवश्यकता है List<SyndEntry>"

इसे ठीक करने का एक उपयुक्त तरीका क्या है?

जवाबों:


96

चूंकि getEntriesएक कच्चा रिटर्न देता है List, यह कुछ भी पकड़ सकता है।

चेतावनी-मुक्त दृष्टिकोण एक नया बनाना है List<SyndEntry>, फिर sf.getEntries()परिणाम के प्रत्येक तत्व SyndEntryको अपनी नई सूची में जोड़ने से पहले कास्ट करें। आपके लिए यह जाँच नहींCollections.checkedList करता है - हालाँकि ऐसा करने के लिए इसे लागू करना संभव होगा।

अपने स्वयं के कलाकारों को सामने रखकर, आप जावा जेनरिक के "वारंटी शर्तों का अनुपालन कर रहे हैं": यदि ClassCastExceptionउठाया जाता है, तो यह स्रोत कोड में एक कास्ट के साथ जुड़ा होगा, न कि संकलक द्वारा डाला गया एक अदृश्य डाली।


9
धन्यवाद - यह "वारंटी" और संकलक द्वारा किए गए अदृश्य कलाकारों के बारे में एक दिलचस्प अंतर्दृष्टि है। मेरे अपने कोड में स्पष्ट रूप से किया गया एक कलाकार।
user46277 5

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

हाय एरिकसन, मैं मानता हूं कि यह वास्तव में सबसे अच्छा समाधान है। इस समाधान के एक सामान्य संस्करण के लिए मेरे उत्तर stackoverflow.com/questions/367626/… की जाँच करें ।
ब्रूनो डी फेन

115

प्री-जावा 5 एपीआई के साथ काम करते समय यह एक आम समस्या है। एरिकसन से समाधान को स्वचालित करने के लिए , आप निम्नलिखित सामान्य विधि बना सकते हैं:

public static <T> List<T> castList(Class<? extends T> clazz, Collection<?> c) {
    List<T> r = new ArrayList<T>(c.size());
    for(Object o: c)
      r.add(clazz.cast(o));
    return r;
}

यह आपको करने की अनुमति देता है:

List<SyndEntry> entries = castList(SyndEntry.class, sf.getEntries());

क्योंकि यह समाधान जांचता है कि तत्वों में वास्तव में कलाकारों के माध्यम से सही तत्व प्रकार है, यह सुरक्षित है, और इसकी आवश्यकता नहीं है SuppressWarnings


5
ब्रूनो द्वारा सुझाई गई विधि के बारे में, कई तत्वों के साथ सूचियाँ होने पर, यह आवेदन के प्रदर्शन को चोट नहीं पहुँचाएगा। जावा को उनमें से हर एक को कास्ट करना होगा।

2
यदि आप गारंटी चाहते हैं, तो यह लागत है। क्या एक और कम महंगा विकल्प है? जाहिर है, यदि आपके पास आह्वान किए गए कच्चे संग्रह रिटर्निंग विधि पर नियंत्रण है, या यहां तक ​​कि विधि को लागू करने या एक आलसी-मांग दृष्टिकोण का उपयोग करके संग्रह तक पहुंच है। कुछ भी जो विधि आह्वान के बाद पूरे संग्रह पर विचार करता है?
डैन

28

ऐसा लगता SyndFeedहै कि जेनरिक का उपयोग नहीं कर रहा है।

आप या तो एक असुरक्षित डाली और चेतावनी दमन कर सकते हैं:

@SuppressWarnings("unchecked")
List<SyndEntry> entries = (List<SyndEntry>) sf.getEntries();

या Collections.checkedList को कॉल करें - हालाँकि आपको अभी भी चेतावनी को दबाने की आवश्यकता होगी:

@SuppressWarnings("unchecked")
List<SyndEntry> entries = Collections.checkedList(sf.getEntries(), SyndEntry.class);

चूँकि वे दोनों चेतावनी को दबाते हैं, एक या दूसरे को कोई लाभ, या वरीयता? धन्यवाद! इसके अलावा: यदि आवश्यक अनियंत्रित दमन होता है, तो क्या कलाकार आवश्यक है?
दान रोसेनस्टार्क

3
@ यार: ठीक है, Collections.checkedListबाद में किसी भी गैर-सिंडिकेट तत्वों को जोड़ने से रोक देगा। मैं व्यक्तिगत रूप से checkedListज्यादा उपयोग नहीं करता हूं , लेकिन फिर मैं भी अक्सर इस अनियंत्रित डाली स्थिति में नहीं आता ...
जॉन स्कीट

9

आपने लिखा था SyndFeed?

करता sf.getEntriesलौट सूची या List<SyndEntry>? मेरा अनुमान है कि यह रिटर्न है Listऔर इसे वापस करने के लिए बदलने List<SyndEntry>से समस्या ठीक हो जाएगी।

यदि आप SyndFeedलाइब्रेरी का हिस्सा हैं, तो मुझे नहीं लगता कि आप @SuppressWarning("unchecked")एनोटेशन को अपने तरीके से जोड़े बिना चेतावनी को हटा सकते हैं ।


आप एक स्पष्ट कलाकारों को भी जोड़ सकते हैं।
उरई

3
एक कलाकार सिर्फ एक और चेतावनी देगा, क्योंकि कोड सुरक्षित नहीं है।
इरिकसन

SyndFeedrometools.github.io/rome/ROMEReleases/ROME1.0Release.html से आता है । समस्या रोम के अधिक हाल के संस्करणों में तय होने लगती है जैसे mvnrepository.com/artifact/com.rometools/rome/1.9.0 पर
daloonik

2

यदि आप अमरूद का उपयोग कर रहे हैं और आप जो करना चाहते हैं वह आपके मूल्यों के माध्यम से करना है:

for(SyndEntry entry: Iterables.filter(sf.getEntries(), SyndEntry.class){
  ...
}

यदि आपको वास्तविक सूची की आवश्यकता है तो आप इसका उपयोग कर सकते हैं

List<SyndEntry> list = Lists.newArrayList(
    Iterables.filter(sf.getEntries(), SyndEntry.class));

या

List<SyndEntry> list = ImmutableList.copyOf(
    Iterables.filter(sf.getEntries(), SyndEntry.class));

1
SyndFeedInput fr = new SyndFeedInput();
SyndFeed sf = fr.build(new XmlReader(myInputStream));
List<?> entries = sf.getEntries();

2
यहां तक ​​कि अगर यहां प्रदान किया गया कोड समस्या को हल करता है, तो मैं आपको संक्षेप में यह बताने के लिए प्रोत्साहित करूंगा कि यह ऐसा क्यों करता है। कृपया बताएं कि पोस्ट किया गया उत्तर समस्या को हल क्यों करता है।
सब्रतला

1

यदि आप वर्ग के लिए javadoc को देखते हैं SyndFeed (मुझे लगता है कि आप कक्षा का उल्लेख कर रहे हैं com.sun.syndication.feed.synd.SyndFeed), विधि getEntries () वापस नहीं आती है java.util.List<SyndEntry>, लेकिन बस वापस आती है java.util.List

तो आपको इसके लिए एक स्पष्ट कलाकार की आवश्यकता है।


0

यदि आप प्रत्येक sf.getEntries () कॉल पर @SuppressWarning ("अनियंत्रित") नहीं डालना चाहते हैं, तो आप हमेशा एक रैपर बना सकते हैं जो सूची वापस कर देगा।

यह अन्य प्रश्न देखें


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