2008-11-04 19 views
185

डाली मेरी वसंत आवेदन संदर्भ फ़ाइल में, मैं की तरह कुछ है:प्रकार की सुरक्षा: अनियंत्रित

तरह
<util:map id="someMap" map-class="java.util.HashMap" key-type="java.lang.String" value-type="java.lang.String"> 
    <entry key="some_key" value="some value" /> 
    <entry key="some_key_2" value="some value" /> 
</util:map> 

जावा वर्ग में, कार्यान्वयन दिखता है:

private Map<String, String> someMap = new HashMap<String, String>(); 
someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap"); 

ग्रहण में, मैं एक चेतावनी दिखाई कि कहते हैं:

प्रकार की सुरक्षा: अनियंत्रित

HashMap को वस्तु से डाली

मैंने क्या गलत किया? मैं इस मुद्दे को कैसे हल करूं?

+0

संबंधित/शिकार: [मैं अनियंत्रित डाली चेतावनी को कैसे संबोधित करते हैं?] (Http://stackoverflow.com/q/509076) – blahdiblah

+0

संभव डुप्लिकेट [मैं अनचेक कास्ट चेतावनियों को कैसे संबोधित करूं?] (http://stackoverflow.com/questions/509076/how-do-i-address-unchecked-cast-warnings) –

+0

मैं वास्तव में कलाकारों की जांच करने के लिए नियमित रूप से आया पैराशनाइज्ड हैश मैप, जो अनचेक कास्ट चेतावनी को समाप्त करता है: [link] (http://stackoverflow.com/questions/509076/how-do-i-address-unchecked-cast-warnings/509230#509230) मैं यह कहूंगा "सही" समाधान है, लेकिन इसके लायक है या नहीं, यह बहस योग्य हो सकता है। :) – skiphoppy

उत्तर

211

ठीक है, सबसे पहले, आप नए HashMap निर्माण कॉल के साथ स्मृति बर्बाद कर रहे हैं। आपकी दूसरी पंक्ति पूरी तरह से इस निर्मित हैशप के संदर्भ को अनदेखा करती है, जिससे इसे कचरा कलेक्टर के लिए उपलब्ध कराया जाता है। तो, ऐसा नहीं करते हैं कि, उपयोग:

private Map<String, String> someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap"); 

दूसरे, संकलक शिकायत कर रहा है कि आप पता चल सके कि यह एक HashMap है बिना एक HashMap करने के लिए वस्तु डाली। लेकिन, अगर आप ऐसा करना चाहते थे:

if(getApplicationContext().getBean("someMap") instanceof HashMap) { 
    private Map<String, String> someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap"); 
} 

आपको शायद यह चेतावनी भी मिल जाएगी। समस्या यह है कि, getBeanObject देता है, इसलिए यह अज्ञात है कि प्रकार क्या है। इसे HashMap में कनवर्ट करने से सीधे दूसरे मामले में समस्या नहीं आती है (और शायद पहले मामले में कोई चेतावनी नहीं होगी, मुझे यकीन नहीं है कि जावा कंपाइलर को जावा 5 के लिए चेतावनियों के साथ पैडेंटिक कैसे है)। हालांकि, आप इसे HashMap<String, String> में परिवर्तित कर रहे हैं।

हैशमैप्स वास्तव में ऐसे मानचित्र हैं जो किसी ऑब्जेक्ट को एक कुंजी के रूप में लेते हैं और यदि आप चाहें तो HashMap<Object, Object> के रूप में ऑब्जेक्ट लेते हैं। इस प्रकार, इस बात की कोई गारंटी नहीं है कि जब आप अपनी बीन प्राप्त करते हैं तो इसे HashMap<String, String> के रूप में प्रदर्शित किया जा सकता है क्योंकि आपके पास HashMap<Date, Calendar> हो सकता है क्योंकि लौटाए गए गैर-सामान्य प्रतिनिधित्व में कोई ऑब्जेक्ट हो सकता है।

यदि कोड संकलित करता है, और आप बिना किसी त्रुटि के String value = map.get("thisString"); निष्पादित कर सकते हैं, तो इस चेतावनी के बारे में चिंता न करें। लेकिन यदि नक्शा स्ट्रिंग कुंजियों के लिए स्ट्रिंग कुंजियों से पूरी तरह से नहीं है, तो आपको रनटाइम पर ClassCastException मिलेगा, क्योंकि जेनेरिक इस मामले में ऐसा होने से अवरुद्ध नहीं कर सकते हैं।

+10

यह थोड़ी देर पहले था, लेकिन मैं एक कास्ट से पहले सेट सेट करने के प्रकार पर एक उत्तर की तलाश कर रहा था, और आप एक पैरामीरिज्ड जेनेरिक पर उदाहरण नहीं दे सकते। जैसे अगर (event.getTarget उदाहरण सेट ) आप केवल एक जेनेरिक जांच सकते हैं? और वह कास्ट चेतावनी को नहीं हटाएगा। जैसे अगर (event.getTarget उदाहरण सेट ) – garlicman

21

एक चेतावनी बस यही है। चेतावनी। कभी-कभी चेतावनियां अप्रासंगिक होती हैं, कभी-कभी वे नहीं होती हैं। उनका उपयोग उस चीज़ पर आपका ध्यान देने के लिए किया जाता है जो संकलक सोचता है कि समस्या हो सकती है, लेकिन हो सकता है।

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

@SuppressWarnings (value="unchecked") 
+8

-1: एक चेतावनी कभी स्वीकार नहीं की जानी चाहिए। या इस तरह की चेतावनियों को दबाएं या इसे ठीक करें। वह क्षण आएगा जहां आपको कई चेतावनियां मिलेंगी और आप एक बार प्रासंगिक नहीं देखेंगे। – ezdazuzena

+5

पैरामीटर जेनरिक्स i.e मानचित्र कास्टिंग करते समय आप वास्तव में क्लास कास्ट चेतावनियों से बच नहीं सकते हैं, इसलिए यह मूल प्रश्न के लिए सबसे अच्छा जवाब है। – muttonUp

9

आपको यह संदेश मिल रहा है क्योंकि GetBean एक ऑब्जेक्ट संदर्भ देता है और आप इसे सही प्रकार पर कास्टिंग कर रहे हैं। जावा 1.5 आपको एक चेतावनी देता है। जावा 1.5 का उपयोग करने की प्रकृति या कोड के साथ बेहतर है जो इस तरह काम करता है। वसंत में टाइपएफ़ संस्करण

someMap=getApplicationContext().getBean<HashMap<String, String>>("someMap"); 

अपनी टोडो सूची पर है।

248

समस्या यह है कि एक डाली एक क्रम की जांच है - लेकिन प्रकार विलोपन के कारण, कार्यावधि में वहाँ वास्तव में किसी भी अन्य Foo और Bar के लिए एक HashMap<String,String> और HashMap<Foo,Bar> बीच कोई अंतर नहीं है।

@SuppressWarnings("unchecked") का उपयोग करें और अपनी नाक पकड़ें। ओह, और जावा में reified जेनरिक :)

+12

मैं जावा के संशोधित जेनेरिकों को बिना किसी एनएसएमयूटेबल पर ले जाऊंगा जो कुछ भी सप्ताह के किसी भी दिन, दस साल की छलांग की तरह महसूस करता है। कम से कम जावा कोशिश कर रहा है। –

+11

बिल्कुल। यदि आप टाइपिंग जांच पर जोर देते हैं, तो इसे केवल हैश मैप के साथ किया जा सकता है और यह सामान्य प्रकार की जांच प्रकार के प्रकार के बाद से चेतावनी को नहीं हटाएगा। यह दुनिया का अंत नहीं है, लेकिन परेशान है कि आप या तो चेतावनी दबाने या इसके साथ रहने के लिए पकड़े गए हैं। – garlicman

+1

@ जोन्स स्केट एक सामान्य जेनेरिक क्या है? – SasQ

53

के रूप में संदेशों के ठीक ऊपर से संकेत मिलता है के लिए अभियान, सूची एक List<Object> और एक List<String> या List<Integer> के बीच अलग नहीं किया जा सकता।

मैं एक ऐसी ही समस्या के लिए यह त्रुटि संदेश हल किया है:

List<?> strList = (List<?>) someFunction(); 
String s = (String) strList.get(0); 

स्पष्टीकरण::

List<String> strList = (List<String>) someFunction(); 
String s = strList.get(0); 
निम्नलिखित के साथ

पहले प्रकार रूपांतरण पुष्टि करता है कि वस्तु के बारे में देखभाल के बिना एक सूची है भीतर रखे गए प्रकार (चूंकि हम सूची स्तर पर आंतरिक प्रकारों को सत्यापित नहीं कर सकते हैं)। दूसरा रूपांतरण अब आवश्यक है क्योंकि संकलक केवल सूची जानता है कि कुछ प्रकार की ऑब्जेक्ट्स हैं। यह सूची में प्रत्येक वस्तु के प्रकार को सत्यापित करता है क्योंकि इसे एक्सेस किया जाता है।

+1

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

+0

इसने चेतावनी को हटा दिया लेकिन फिर भी मुझे विश्वास नहीं है: पी – mumair

4

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

उदाहरण के लिए, आप

private Map<String, String> someMap = new HashMap<String, String>(); 

उपयोग करने के लिए कोशिश कर रहे हैं आप तो ऐसे

public class StringMap extends HashMap<String, String>() 
{ 
    // Override constructors 
} 

की तरह एक नया वर्ग पैदा कर सकते हैं जब आप

someMap = (StringMap) getApplicationContext().getBean("someMap"); 

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

1

एक और समाधान, यदि आप स्वयं को एक ही वस्तु कास्टिंग करते हैं तो आप @SupressWarnings("unchecked") के साथ अपना कोड कूड़ा नहीं करना चाहते हैं, तो एनोटेशन के साथ एक विधि बनाना होगा। इस तरह आप कास्ट को केंद्रीकृत कर रहे हैं, और उम्मीद है कि त्रुटि की संभावना कम हो जाएगी।

@SuppressWarnings("unchecked") 
public static List<String> getFooStrings(Map<String, List<String>> ctx) { 
    return (List<String>) ctx.get("foos"); 
} 
0

कोड नीचे क्योंकि वस्तु के प्रकार के आयोजित मापदंडों का उल्लेख किए बिना प्रकार सुरक्षा चेतावनी

Map<String, Object> myInput = (Map<String, Object>) myRequest.get();

वर्कअराउंड

एक नया मानचित्र वस्तु बनाएं का कारण बनता है सूची में एन है ओटी सत्यापित

चरण 1: एक नया अस्थायी मानचित्र

बनाएं

Map<?, ?> tempMap = (Map<?, ?>) myRequest.get();

चरण 2: का दृष्टांत मुख्य मानचित्र

Map<String, Object> myInput=new HashMap<>(myInputObj.size()); 

चरण 3: दोहराएं अस्थायी मानचित्र और मुख्य मानचित्र में मूल्यों को निर्धारित

for(Map.Entry<?, ?> entry :myInputObj.entrySet()){ 
     myInput.put((String)entry.getKey(),entry.getValue()); 
    } 
संबंधित मुद्दे