2012-05-17 8 views
46

के साथ संदिग्ध ओवरलोडेड जावा विधियां मैं समझने की कोशिश कर रहा हूं कि जावा कॉल फ़ंक्शन कॉल में अस्पष्टताओं से कैसे निपटता है। निम्नलिखित कोड में, method पर कॉल संदिग्ध है, लेकिन method2 नहीं है !!!जेनेरिक और varargs

मुझे लगता है कि दोनों संदिग्ध हैं, लेकिन जब मैं method पर कॉल पर टिप्पणी करता हूं तो यह संकलित क्यों होता है? method2 क्यों संदिग्ध नहीं है?

public class A { 
    public static <K> List<K> method(final K arg, final Object... otherArgs) { 
     System.out.println("I'm in one"); 
     return new ArrayList<K>(); 
    } 

    public static <K> List<K> method(final Object... otherArgs) { 
     System.out.println("I'm in two"); 
     return new ArrayList<K>(); 
    } 

    public static <K, V> Map<K, V> method2(final K k0, final V v0, final Object... keysAndValues) { 
     System.out.println("I'm in one"); 
     return new HashMap<K,V>(); 
    } 

    public static <K, V> Map<K, V> method2(final Object... keysAndValues) { 
     System.out.println("I'm in two"); 
     return new HashMap<K,V>(); 
    } 

    public static void main(String[] args) { 
     Map<String, Integer> c = A.method2("ACD", new Integer(4), "DFAD"); 
     //List<Integer> d = A.method(1, "2", 3 ); 
    } 
} 

संपादित करें: इस टिप्पणी में आया: IDEs का एक नंबर दोनों की रिपोर्ट के रूप में अस्पष्ट - इंटेलीजे और Netbeans अब तक। हालांकि, यह कमांड लाइन/मेवेन से ठीक है।

+0

अच्छा प्रश्न ... – Jivings

+0

शायद यह संकलन समय में वृद्धि होगी अगर जावा अप्रयुक्त तरीकों – Joelmob

+0

@Joelmob मुझे लगता है सवाल यह है कि के लिए जाँच क्यों करता है 'method2' संकलन जब यह बस के रूप में हो रहा है 'विधि' के रूप में संदिग्ध। – Jivings

उत्तर

14

परीक्षण करने के लिए है कि क्या method1method2 की तुलना में अधिक विशिष्ट है एक सहज तरीके से देखने के लिए समान पैरामीटर

method1(params1){ 
    method2(params1); // if compiles, method1 is more specific than method2 
} 

साथ method2 लागू द्वारा चाहे method1 लागू किया जा सकता वहाँ varargs हैं, तो हम एक vararg का विस्तार करने की आवश्यकता हो सकती है ताकि 2 विधियों में समान संख्या में पैराम हों।

के अपने उदाहरण में पहले दो method() रों जाँच करें

<K> void method_a(K arg, Object... otherArgs) { 
    method_b(arg, otherArgs); //ok L1 
} 
<K> void method_b(Object arg, Object... otherArgs) { // extract 1 arg from vararg 
    method_a(arg, otherArgs); //ok L2 
} 

(वापसी प्रकार विशिष्टता का निर्धारण करने में उपयोग नहीं किया जाता है, ताकि वे छोड़े गए हैं) दोनों संकलन, इसलिए प्रत्येक की तुलना में अधिक विशिष्ट है अन्य, इसलिए अस्पष्टता। आपके method2() एस के लिए भी जाता है, वे एक-दूसरे से अधिक विशिष्ट होते हैं। इसलिए method2() पर कॉल संदिग्ध है और संकलित नहीं होना चाहिए; अन्यथा यह एक कंपाइलर बग है।


तो यही बात कहती है; लेकिन क्या यह उचित है? निश्चित रूप से, method_amethod_b से अधिक विशिष्ट दिखता है। वास्तव में अगर हम K

void method_a(Integer arg, Object... otherArgs) { 
    method_b(arg, otherArgs); // ok 
} 
void method_b(Object arg, Object... otherArgs) { 
    method_a(arg, otherArgs); // error 
} 

के बजाय एक ठोस प्रकार है उसके बाद ही method_amethod_b की तुलना में अधिक विशिष्ट, इसके विपरीत नहीं है।

विसंगति के प्रकार से विसंगति उत्पन्न होती है। L1/L2 स्पष्ट प्रकार के तर्कों के बिना एक सामान्य विधि को कॉल करता है, इसलिए संकलक प्रकार तर्कों का अनुमान लगाने का प्रयास करता है। लक्ष्य प्रकार अनुमान एल्गोरिदम प्रकार तर्क तर्क खोजने के लिए है कि कोड संकलित करता है! कोई आश्चर्य नहीं कि एल 1 और एल 2 संकलन। एल 2 वास्तव में this.<Object>method_a(arg, otherArgs)

टाइप अनुमान अनुमान लगाने का प्रयास करता है कि प्रोग्रामर क्या चाहता है, लेकिन अनुमान कभी-कभी गलत होना चाहिए। हमारा असली इरादा वास्तव में है

<K> void method_a(K arg, Object... otherArgs) { 
    this.<K>method_b(arg, otherArgs); // ok 
} 
<K> void method_b(Object arg, Object... otherArgs) { 
    this.<K>method_a(arg, otherArgs); // error 
} 
+0

अंतर्ज्ञानी परीक्षण के लिए धन्यवाद .. लेकिन यह सवाल का जवाब नहीं देता है। प्रश्न यह है कि विधि ** का प्रकटीकरण ** विफल क्यों होता है लेकिन method2 ** ** पास करता है। विश्लेषण से – Chip

+2

, 'method2' पर कॉल करें * सबसे विशिष्ट * विधि की कमी के लिए संदिग्ध है। इसलिए यह एक कंपाइलर बग है। – irreputable

+0

यदि आप उत्तर में यह स्पष्ट करते हैं .. मैं इसे स्वीकार करूंगा। – Chip