विधि अशक्त तर्क के लिए अतिभार


133

मैंने मापदंडों के साथ तीन विधियाँ जोड़ी हैं:

public static  void doSomething(Object obj) {
    System.out.println("Object called");
}

public static  void doSomething(char[] obj) {
    System.out.println("Array called");
}

public static  void doSomething(Integer obj) {
    System.out.println("Integer called");
}

जब मैं फोन कर रहा होता हूं doSomething(null), तब कंपाइलर अस्पष्ट तरीकों के रूप में त्रुटि फेंकता है । तो मुद्दा है क्योंकि Integerऔर char[]तरीकों या Integerऔर Objectतरीकों?


3
बस Integerकरने के लिए बदल जाते हैं int
मुदस्सिर

2
@ मुदासिर: और वास्तव में क्या हल होगा?
जोकिम सॉर

2
@ जोकिम सॉयर: यदि इंटिजर से इंट में बदल दिया जाता है, तो जावा में प्राइमरी प्रकार के नल को संदर्भित नहीं किया जाता है, इसलिए कंपाइलर त्रुटि नहीं करेगा।
फणी

@ जोकिम सौर: यह reference to doSomething is ambiguousत्रुटि नहीं फेंकेंगे ।
मुदस्सिर

जवाबों:


211

जावा हमेशा उपलब्ध विधि के सबसे विशिष्ट लागू संस्करण का उपयोग करने की कोशिश करेगा (देखें JLS .1215.12.2 )।

Object, char[]और Integerसभी nullएक वैध मूल्य के रूप में ले सकते हैं । इसलिए सभी 3 संस्करण लागू हैं, इसलिए जावा को सबसे विशिष्ट एक खोजना होगा।

चूंकि Object, सुपर-प्रकार है char[], सरणी संस्करण Object-version की तुलना में अधिक विशिष्ट है । इसलिए यदि केवल वे दो विधियाँ मौजूद हैं, तो char[]संस्करण चुना जाएगा।

जब दोनों char[]और Integerसंस्करण उपलब्ध होते हैं, तो दोनों की तुलना में अधिक विशिष्ट होते हैं, Objectलेकिन कोई भी अन्य की तुलना में अधिक विशिष्ट नहीं है, इसलिए जावा यह तय नहीं कर सकता है कि किसको कॉल करना है। इस मामले में आपको स्पष्ट रूप से उल्लेख करना होगा कि आप किस तर्क को उपयुक्त प्रकार से कॉल करके कॉल करना चाहते हैं।

ध्यान दें कि व्यवहार में यह समस्या शायद ही कभी और अधिक हो सकती है। इसका कारण यह है कि यह केवल तब होता है जब आप स्पष्ट रूप nullसे किसी विशिष्ट-विशिष्ट प्रकार (जैसे जैसे Object) के चर के साथ एक विधि कह रहे हों ।

इसके विपरीत, निम्नलिखित आह्वान पूरी तरह से अस्पष्ट होगा:

char[] x = null;
doSomething(x);

हालाँकि आप अभी भी मान पास कर रहे हैं null, जावा को पता है कि किस विधि से कॉल करना है, क्योंकि यह चर के प्रकार को ध्यान में रखेगा।


1
यह जावा 7 के लिए कहा गया है। क्या यह पिछले जावा संस्करणों पर भी लागू होता है? मेरा मतलब है: यदि आपके पास केवल एक प्रकार की पदानुक्रम के साथ मापदंडों के साथ कई विधि हस्ताक्षर हैं, तो आप वास्तविक मूल्य के रूप में अशक्त के साथ बचत पक्ष पर हैं? और अगर आपने यहां उदाहरण में "के लिए" पदानुक्रम बनाया है, तो आप नहीं हैं?
क्रिश्चियन गोस्च

2
मुझे पूरा यकीन है कि वे नियम जावा 1.1 के बाद से कम से कम सब कुछ के लिए समान हैं (सामान्य रूप से जोड़ के अलावा, स्पष्ट रूप से)।
जोकिम सॉयर

क्या इसका मतलब यह है कि यदि संकलक doSomething (String str) और doSomething (ऑब्जेक्ट obj) के बीच में रनटाइम के दौरान doSomething (null) के साथ चुनना है, doSomething (String str) को कहा जाएगा।
समीर

43

इन तीन विधियों में से प्रत्येक जोड़ी अपने आप से अस्पष्ट है जब एक के साथ बुलाया जाता है null तर्क के है। क्योंकि प्रत्येक पैरामीटर प्रकार एक संदर्भ प्रकार है।

नल के साथ आपकी एक विशिष्ट विधि को कॉल करने के तीन तरीके निम्नलिखित हैं।

doSomething( (Object) null);
doSomething( (Integer) null);
doSomething( (char[]) null);

अगर मैं वास्तव में इन तरीकों को nullतर्कों के साथ सुनाने की योजना बनाऊं तो मुझे इस अस्पष्टता को दूर करने का सुझाव देना चाहिए । ऐसा डिज़ाइन भविष्य में त्रुटियों को आमंत्रित करता है।


1
केवल Integer- char[]जोड़ी अस्पष्ट है, क्योंकि अन्य दो मामलों में, जावा कंपाइलर सबसे विशिष्ट विकल्प चुन सकता है, जैसे @JoachimSauh वर्णित है।
काजाक्स

1
@kajacx: ​​ओपी मूल प्रश्न इन विधियों nullको पैरामीटर के रूप में कॉल करने के बारे में था । उस पूर्व शर्त के तहत, सभी तीन जोड़े अस्पष्ट हैं। सामान्य मामले के लिए, मैं सहमत हूं कि केवल Integer - char[]जोड़ी अस्पष्ट है।
jmg

के बारे में क्या doSomething(null)के लिए public static void doSomething(String str) { System.out.println("String called"); } यह कहा जाता है स्ट्रिंग वापस आ जाएगी।
समीर

क्या "nullable" या "nullable" जैसे एनोटेशन का उपयोग करना संभव है और घोषणाओं को सेट करना है, इसलिए केवल एक विधि जिसे आप एक नल प्राप्त करना चाहते हैं ताकि एक स्पष्ट "null" (अभी तक निहित शून्य प्रकार) तर्क हमेशा स्पष्ट रूप से चयन करता है एक विशिष्ट अधिभार ??
याचिकाकर्ता

4

nullतीन प्रकारों में से किसी के लिए एक वैध मूल्य है; इसलिए कंपाइलर यह तय नहीं कर सकता कि किस फंक्शन का इस्तेमाल करना है। इसके बजाय doSomething((Object)null)या कुछ का उपयोग करें doSomething((Integer)null)


मैंने इंटीजर पैरामीटर के साथ विधि को हटा दिया, यह फ़ंक्शन और रिटर्निंग आउटपुट को "एरे कॉल" के रूप में आमंत्रित कर रहा है , इसलिए एरे और ऑब्जेक्ट के बीच क्या अनुबंध है ?
फणी

2
जावा एरेज़ भी ऑब्जेक्ट हैं।
ZDS

2

जावा में हर वर्ग ऑब्जेक्ट क्लास का विस्तार करता है। एवेंजर वर्ग भी ऑब्जेक्ट का विस्तार करता है। इसलिए ऑब्जेक्ट और इंटेगर दोनों को ऑब्जेक्ट उदाहरण माना जाता है। इसलिए जब आप कंपाइलर से एक पैरामीटर के रूप में नल को पास करते हैं, तो भ्रमित हो जाता है कि किस ऑब्जेक्ट को कॉल करने के लिए ऑब्जेक्ट पैरामीटर या पैरामीटर Integer के साथ है क्योंकि वे दोनों ऑब्जेक्ट हैं और उनका संदर्भ शून्य हो सकता है। लेकिन जावा में आदिम वस्तु का विस्तार नहीं करता है।


1

मैंने यह कोशिश की है और जब पूरी तरह से ओवरलोड विधि की एक जोड़ी है और उनमें से एक में पैरामीटर प्रकार ऑब्जेक्ट है तो कंपाइलर हमेशा अधिक विशिष्ट प्रकार के साथ विधि का चयन करेगा। लेकिन जब एक से अधिक विशिष्ट प्रकार होते हैं, तो कंपाइलर एक अस्पष्ट विधि त्रुटि फेंकता है।

चूंकि यह एक संकलित समय घटना है, यह केवल तभी हो सकता है जब कोई जानबूझकर इस पद्धति को शून्य कर देता है। यदि यह जानबूझकर किया जाता है, तो इस पद्धति को फिर से अधिभार देना बेहतर है, जिसमें कोई पैरामीटर नहीं है या पूरी तरह से एक और विधि बना सकते हैं।


0

doSomething (char [] obj) और doSomething (Integer obj) के कारण अस्पष्टता है।

चार [] और पूर्णांक दोनों ही अशक्तों के लिए समान श्रेष्ठ हैं कि वे अस्पष्ट क्यों हैं।


0
class Sample{
  public static void main (String[] args) {
       Sample s = new Sample();
       s.printVal(null);

    } 
    public static void printVal(Object i){
        System.out.println("obj called "+i);
    }

    public static void printVal(Integer i){
        System.out.println("Int called "+i);
    }
}

आउटपुट Int को null कहा जाता है और इसलिए अस्पष्टता char [] और Integer के साथ है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.