2015-01-17 14 views
6

निम्नलिखित कोडजावा जेनेरिक विधि। टी को मानचित्र क्यों माना जाता है?

class MyClass { 
    public MyClass(Map<String, String> m) { 
     System.out.println("map"); 
    } 

    public MyClass(SortedMap<String, String> m) { 
     System.out.println("sortedmap"); 
    } 
} 
public class Test { 

    public <T extends Map<String,String>> Test(T t) { 
     new MyClass(t); 
    } 

    public static void main(String[] args) { 
     new Test(new TreeMap<String,String>()); 
    } 

} 

यह प्रिंट map पर विचार करें। T में SortedMap के बजाय Map क्यों निकाला गया है? MyClass के लिए सबसे ठोस कन्स्ट्रक्टर का उपयोग करने के लिए इस व्यवहार को बदलने का कोई तरीका है?

उत्तर

4

संकल्प जो MyClass का कन्स्ट्रक्टर संकलित समय पर किया जाता है। जब संकलक Test कन्स्ट्रक्टर के कोड को संकलित करता है, तो यह नहीं पता कि T वास्तव में क्या है, यह केवल यह जानता है कि यह Map<String, String> होने की गारंटी है, इसलिए यह Map लेने वाले निर्माता को कन्स्ट्रक्टर कॉल को बाध्य करने से कुछ और नहीं कर सकता । ज्ञान जो आपके कोड T में है TreeMap केवल main विधि के भीतर मौजूद है, बाहर नहीं। उदाहरण के लिए विचार करें कि क्या होगा यदि आपने Test कन्स्ट्रक्टर का दूसरा कॉलर जोड़ा जो वास्तव में HashMap पास करता है।

जावा जेनेरिक काम करते हैं कि जेनेरिक विधि का कोड केवल सभी संभावित जेनेरिक पैरामीटर मानों (और बाइट कोड में केवल एक बार मौजूद) के लिए संकलित किया जाता है, अन्य भाषाओं में जेनेरिक विधि की एक प्रति नहीं है प्रत्येक सामान्य प्रकार।

सामान्य रूप से, जावा में संभवतः कोड में एक विधि/कन्स्ट्रक्टर कॉल को अलग-अलग तर्क/कन्स्ट्रक्टर पर तर्क के प्रकार के आधार पर कॉल करने के लिए संभव नहीं है। यह कॉल ऑब्जेक्ट के रनटाइम प्रकार (अधिलेखित विधियों के साथ गतिशील बाध्यकारी) के आधार पर विधि कॉल के लिए केवल संभव है।

ओवरलोडिंग (जो आपके पास है) केवल तर्कों के स्थिर प्रकार को देखकर संकलित समय पर काम करता है।

इस स्थिति के लिए सामान्य समाधान MyClass के निर्माता के भीतर जांच करना होगा। एक और संभावित (अधिक सुरुचिपूर्ण) समाधान विज़िटर पैटर्न है, लेकिन यह केवल उन कक्षाओं के साथ काम करता है जो इसके लिए तैयार हैं (इसलिए Map उदाहरणों के साथ नहीं, यदि आप उन्हें अपनी कक्षा में लपेटते नहीं हैं)।

+0

यह कैसे है कि संकलक को यह नहीं पता कि वास्तव में 'टी' किस प्रकार का है? मैं इसे 'ट्रीमैप' के रूप में बना रहा हूं (मैं व्यवहार को समझूंगा यदि कन्स्ट्रक्टर को 'मैप' के रूप में घोषित ऑब्जेक्ट को गुजरने का आह्वान किया गया था, वास्तव में 'ट्रीमैप' था, लेकिन ऐसा नहीं है) –

+2

ओह, मैं उम्मीद कर रहा था एक ही जेनेरिक विधि में 'टी' के विभिन्न संस्करणों के लिए अलग-अलग कोड उत्पन्न करने के लिए। मुझे लगता है कि जावा सी ++ नहीं है। उत्तर के लिए धन्यवाद, अब यह स्पष्ट है। –

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