2015-11-02 5 views
11

मैं एक parametrized मूल्य है, जो रनटाइम के दौरान हल हो गई है:जेनेरिक चर को रनटाइम पर हल होने पर अनचेक कास्ट से कैसे बचें?

public class GenericsMain { 
    public static void main(String... args) { 
     final String tag = "INT"; 

     Field field = resolve(tag); 

     if (tag.equals("INT")) { 
      /* 
       In here I am using the "secret knowledge" that if tag equals INT, then 
       field could be casted to Field<Integer>. But at the same time I see an unchecked cast 
       warning at here. 

       Is there a way to refactor the code to be warning-free? 
      */ 
      Field<Integer> integerField = (Field<Integer>) field; 

      foo(integerField); 
     } 
    } 

    public static Field resolve(String tag) { 
     switch (tag) { 
      case "INT": 
       return new Field<>(1); 
      case "DOUBLE": 
       return new Field<>(1.0d); 
      default: 
       return null; 
     } 
    } 

    public static <T> void foo(Field<T> param) { 
     System.out.println(param.value); 
    } 

    static class Field<T> { 
     public final T value; 

     public Field(T value) { 
      this.value = value; 
     } 
    } 
} 

वहाँ एक रास्ता कोड ऊपर (एक लंबे टिप्पणी के साथ चिह्नित) में अनियंत्रित डाली से बचने के लिए है?

+2

सीधे नहीं। (जावा प्रवाह प्रकारों का समर्थन नहीं करता है।) हालांकि आप यहां विज़िटर पैटर्न का उपयोग कर सकते हैं। – aioobe

+1

इस प्रश्न पर एक नज़र डालें: http://stackoverflow.com/questions/1129795/what-is-suppresswarnings-unchecked-in-java – stevecross

+0

@aioobe मैं वास्तव में अच्छा होगा यदि आप एक उदाहरण के साथ विस्तृत करते हैं। –

उत्तर

2

आप ऐसा करने के लिए एनोटेशन का उपयोग कर सकते हैं। एनोटेशन नीचे का उपयोग करें:

@SuppressWarnings("unchecked") 
+4

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

+1

आप इसे सीधे जावा में नहीं कर सकते हैं। –

6

आम तौर पर, कोई रास्ता नहीं है, क्योंकि प्रकार पैरामीटर घोषणा के लिए बाध्य है। और आप क्या करना चाहते हैं रनटाइम मान के आधार पर स्थिर घोषणा को बदलना है।

हालांकि, अगर आप पैरामिट्रीकृत विधि है कि पैरामीटर

@SuppressWarnings("unchecked") 
private static <T> Field<T> asParameterized(Field<?> field) { 
    return (Field<T>) field; 
} 

लिखते हैं और फिर हो सकता है कि

Field<Integer> intField = GenericsMain.<Integer> asParameterized(field); 
+1

कृपया ढेर प्रदूषण के बारे में पढ़ें https://docs.oracle.com/javase/tutorial/java/generics/nonReifiableVarargsType.html#heap_pollution। –

+0

सहमत हैं, यही कारण है कि संकलक चेतावनी को छोड़ देता है, लेकिन यह मामला सुरक्षित दिखता है - किस प्रकार का पैरामीटर होना चाहिए इसका सटीक 'गुप्त' ज्ञान है। –

+0

ठीक है, अगर आप अपने 'गुप्त' ज्ञान पर भरोसा करते हैं, तो मुझे लगता है कि यह ठीक है। लेकिन आपके पास एक बुरा दिन हो सकता है और पूरी तरह से 'फ़ील्ड intField = asParameterized (फ़ील्ड)' 'फ़ील्ड 'के साथ एक डबल होल्डिंग कर सकता है ... ठीक करने और डीबग करने के लिए बहुत आसान नहीं है ... –

3

का उपयोग कहते हैं की घोषणा के द्वारा अनियंत्रित कलाकारों के क्षेत्र को कम कर सकते हैं। गूंगा स्ट्रिंग टैग के बजाय, आप एक प्रकार का उपयोग कर सकते हैं जो प्रकार की जानकारी को एन्कोड करता है। इस ब्लॉग पोस्ट देखें: http://blog.pdark.de/2010/05/28/type-safe-object-map/

public class FieldKey<T> { 
    private String name; 

    public FieldKey(String name) { 
     this.name = name; 
    } 

    public String name() { 
     return name; 
    } 
} 

प्लस public Field(FieldKey<T> key, T value) करने के लिए Field के निर्माता बदलते।

आपको अभी भी कास्ट करना है लेकिन समय जांच संकलित करना सुनिश्चित करेगा कि वे कभी विफल नहीं होंगे।

+3

और आप सही तरीके से पैरामीटर कैसे बना रहे हैं FieldKey उदाहरणों की घोषणा? :) मुझे पूरा यकीन है कि लूप को तोड़ने के लिए कहीं कहीं अनचेक किया जाना चाहिए –

+0

कृपया मेरे ब्लॉग पोस्ट में कोड देखें; आप 'get (TypedMapKey)' विधि में कास्ट देख सकते हैं। आप कास्ट को मुख्य श्रेणी में भी ले जा सकते हैं: 'सार्वजनिक टी प्राप्त करें (फ़ील्ड एफ) '। जैसा कि मैंने कहा, मेरे दृष्टिकोण का मुख्य लाभ यह है कि आप दोनों प्रकार के असाइनमेंट पर पढ़ सकते हैं और पढ़ सकते हैं और इसलिए सुनिश्चित कर सकते हैं कि कलाकार विफल नहीं हो सकता है। –

1

सभी उत्तरों ठीक हैं, लेकिन मुझे लगता है कि पर पर्याप्त जोर नहीं है क्यों आपको चेतावनी मिल रही है और कास्टिंग कर रहे हैं।

आप स्पष्ट रूप से एक अनचेक कास्ट करके टाइप सिस्टम को अवरुद्ध कर रहे हैं। कहकर "मेरे पास इस प्रकार के बारे में जानकारी है जो संकलक के लिए उपलब्ध नहीं है" - आप संकलक को बता रहे हैं कि आप बेहतर जानते हैं।

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

यह सही अर्थ बनाता है। वास्तव में, यदि आप जीएसओएन जैसे पुस्तकालयों की जांच करते हैं जो क्रमबद्धता करते हैं तो वे full of these warnings and supressions हैं।

अपने कोड के बारे में चिंता न करें - यह ठीक है। अगर संकलक को "नकल" करने का कोई तरीका नहीं था जो चेतावनी को उत्सर्जित नहीं करता है जो दूसरी ओर एक गंभीर समस्या होगी :)

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