2010-02-05 16 views
14

मैं एक सामान्य प्रकार बनाने की कोशिश कर रहा हूं जो बाद के उपयोग के लिए बनाए गए संस्करणों का मानचित्र रखता है। प्रभावी रूप से, यह एक सिंगलटन पैटर्न है जहां प्रति प्रकार एक उदाहरण है। मेरे पास अब तक का कोड है:संबंधित प्रकारों के जेनेरिक कुंजी/मानों का सामान्य मानचित्र

public class FieldBinder<T> { 
    static final Map<Class<? extends Object>,FieldBinder<? extends Object>> instanceMap = 
     new HashMap<Class<? extends Object>,FieldBinder<? extends Object>>(); 

    private FieldBinder() {} 

    synchronized public static <V extends Object> FieldBinder<V> getInstance(Class<V> klass) { 
     if(!instanceMap.containsKey(klass)) { 
      instanceMap.put(klass, new FieldBinder<V>()); 
     } 
     return (FieldBinder<V>)instanceMap.get(klass); 
    } 
} 

हालांकि, मुझे अभी भी अनिश्चितता है कि मैं "इसे सही कर रहा हूं"। ऐसा लगता है कि मुझे यह निर्दिष्ट करने में सक्षम होना चाहिए कि संग्रह (कक्षा -> फ़ील्डबिंडर) है। तथ्य यह है कि आईडीई रिटर्न स्टेटमेंट के बारे में चेतावनी दे रहा है केवल इस विचार को मजबूत करता है।

क्या इसे संभालने का कोई बेहतर तरीका है?

नोट: This question बहुत करीबी से संबंधित लगता है, लेकिन बहुत दूर है कि मैं यह नहीं समझ सकता कि इसमें अपनी समस्या के बारे में जानकारी कैसे लागू करें।

उत्तर

14

आपका कार्यान्वयन सही है। यह कर

माइनर फिक्स (अगर कोई है ऐसी बात जो एक और मुद्दा .. है "बेहतर" कोड में है,) का कोई "बेहतर" तरीका उपलब्ध नहीं है:

  • <V extends Object>V है जो के बराबर है कम वर्बोज़
  • Class<? extends Object>Class<?> जो कम वर्बोज़
  • आप अपने संकलक बताने के लिए @SuppressWarnings("unchecked") एनोटेशन का उपयोग कर सकते है के बराबर है कि कलाकारों के लिए सुरक्षित है
1

उदाहरण जो आप संदर्भित करते हैं, वह वस्तु के प्रकार (वर्ग) को कैसे पुनर्प्राप्त करें, जबकि आपको पैरामीट्रिजेशन के प्रकार (वर्ग) को पुनर्प्राप्त करने की आवश्यकता है। यह संभव नहीं है।

+0

मान लीजिए कि मैं समझ रहा हूं कि आप क्या कह रहे हैं, तो यह बिल्कुल नहीं है कि मैं क्या कर रहा हूं। मैं चाहता हूं कि कंपाइलर को यह बताना है कि "यह क्लास 'से' फ़ील्डबिंडर 'से एक नक्शा है, जहां दोनों? एक जैसा होना चाहिए। ऐसे में, जब मैं कुछ = = xyz की कुंजी का उपयोग करके बाहर खींचता हूं, तो मैं सुरक्षित रूप से सुरक्षित कर सकता हूं मानकों को मूल्य = = xyz, क्योंकि संकलक मुझे केवल इस तरह से चीजों को रखने के लिए सीमित कर सकता है। यह सब संकलित समय की जानकारी है, ऐसा लगता है कि संकलक इसे संभाल नहीं सकता है। – RHSeeger

3

मुझे नहीं लगता कि यह कहीं अनचेक कास्ट किए बिना किया जा सकता है। आपको Haskell के existential types के समान कुछ चाहिए, जिसमें जावा नहीं है।

आप बना सकते हैं ग्राहक अनियंत्रित कलाकारों के बजाय प्रदर्शन ...

synchronized public static <V> FieldBinder<V> 
getInstance(Class<V> klass, Class<FieldBinder<V>> binderKlass) { 
    if(!instanceMap.containsKey(klass)) { 
     instanceMap.put(klass, new FieldBinder<V>()); 
    } 
    return binderKlass.cast(instanceMap.get(klass)); 
} 

अब अगर ग्राहक getInstance() विधि आप getInstance() भीतर अनियंत्रित कलाकारों से बच सकते हैं करने के लिए एक Class<FieldBinder<V>> गुजरता है।

दुर्भाग्य से एक Class<FieldBinder<V>> खुद बनाते हुए एक अनियंत्रित कलाकारों की आवश्यकता है।

Class<FieldBinder<Integer>> binderKlass = 
    (Class<FieldBinder<Integer>>) (Class<?>) FieldBinder.class; 
BinderAssociator.getInstance(Integer.class, binderKlass); 
3

आरएचएसगर, मुझे आपका मूल प्रश्न मिला। मुझे समस्या के लिए कोई समाधान नहीं मिला। आप एक मैप मैप क्लास के साथ खेलने का प्रयास कर सकते हैं, जो आपके अनुरोध के अनुसार बाध्यकारी बनाता है। हालांकि इस मानचित्र के साथ दो समस्याएं उत्पन्न हुईं:

  1. क्योंकि इसे MyMap<?> के रूप में घोषित किया गया है, कोई इसे किसी दिए गए प्रकार से कुछ नहीं जोड़ सकता है। यह डमी है और मैं आपको अधिक जानकारी के लिए Java Generics FAQs (केस स्टडी 3 देखें) पर संदर्भित करता हूं।
  2. नक्शा कुंजी और मान के बीच संबंध नहीं है के रूप में, एक किसी भी प्रकार के दो स्वतंत्र वस्तुओं नहीं जोड़ सकते हैं (दो <?> विभिन्न प्रकार को देखें) क्योंकि इन दो प्रकार से नहीं जोड़ा जा सकता है।

खेलते समय मैंने कुछ त्रुटियां देखी हैं, जिन्हें मैं स्वयं समझा नहीं सकता। मुझे लगता है, सबकुछ तथ्य में चला जाता है (जैसा कि मैंने पहले उल्लेख किया था) कि हम 2-स्तर के स्तर पर पैरामीट्रिजेशन से निपटने का प्रयास करते हैं।

class FieldBinder<T> { 
     static class MyMap<M> extends HashMap<Class<M>, FieldBinder<M>> { 
     } 
     static final MyMap<?> instanceMap1 = new MyMap<Object>(); 
     static final Map<Class<?>, FieldBinder<?>> instanceMap2 = new HashMap<Class<?>, FieldBinder<?>>(); 
     public static <V> void test() { 
      Class<V> c1 = null; 
      FieldBinder<V> f1 = null; 
      Class<?> c2 = null; 
      FieldBinder<?> f2 = null; 
      instanceMap1.put(c1, f1); // error (see 1) 
      instanceMap1.put(c2, f2); // error (see 2) 
      instanceMap2.put(c1, f1); // ok 
      instanceMap2.put(c2, f2); // ok 
      instanceMap2.put(c1, f2); // wish to be an error, but ok 
      instanceMap2.put(c2, f1); // wish to be an error, but ok 
     } 
    } 
+0

विस्तृत उत्तर के लिए धन्यवाद। मेरे पास इस तथ्य पर बहुत अच्छी समझ है कि जावा जेनेरिक सिर्फ उस कार्य तक नहीं हैं जो मैं अभी पूरा करना चाहता हूं, और आपके उत्तर ने इसे मजबूत करने में मदद की। मुझे लगता है कि मैं वास्तव में क्या देखना चाहूंगा कहने की क्षमता होगी .. .. स्थैतिक अंतिम मानचित्र , फ़ील्डबिंडर > instanceMap2 = नया हैश मैप , फ़ील्डबिंडर > (); .... जहां का मतलब है "किसी भी प्रकार", लेकिन उस प्रकार को उस चर को बांधता है जिसे बाद में उपयोग किया जा सकता है। – RHSeeger

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