जब एक पैरामीटर शाब्दिक अशक्त मान है, तो एक अधिभारित विधि को कैसे चुना जाता है?


98

मुझे एक क्विज़ में यह प्रश्न आया,

public class MoneyCalc {

   public void method(Object o) {
      System.out.println("Object Verion");
   }

   public void method(String s) {
      System.out.println("String Version");
   }

   public static void main(String args[]) {
      MoneyCalc question = new MoneyCalc();
      question.method(null);
   }
}

इस कार्यक्रम का आउटपुट "स्ट्रिंग संस्करण" है। लेकिन मैं यह समझने में सक्षम नहीं था कि एक अतिभारित पद्धति के लिए एक अशक्तता को पारित करने के लिए स्ट्रिंग संस्करण को क्यों चुना गया। अशक्त स्ट्रिंग चर कुछ भी नहीं की ओर इशारा कर रहा है?

हालाँकि जब कोड को बदल दिया जाता है,

public class MoneyCalc {

   public void method(StringBuffer sb) {
      System.out.println("StringBuffer Verion");
   }

   public void method(String s) {
      System.out.println("String Version");
   }

   public static void main(String args[]) {
      MoneyCalc question = new MoneyCalc();
      question.method(null);
   }
}

यह एक संकलित त्रुटि कहती है "विधि विधि (StringBuffer), MoneyCalc प्रकार के लिए अस्पष्ट है"


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


6
जाहिरा तौर पर यह उन लोगों द्वारा डुप्लिकेट के रूप में बंद कर दिया गया था जो केवल शीर्षक पढ़ते हैं। यहां वास्तविक प्रश्न यह है कि एक विशिष्ट अधिभार क्यों चुना गया, न कि "क्या अशक्त"।
10

जवाबों:


102

अशक्त स्ट्रिंग चर कुछ भी नहीं की ओर इशारा कर रहा है?

अशक्त संदर्भ को किसी भी वर्ग प्रकार की अभिव्यक्ति में बदला जा सकता है। तो इस मामले में String, यह ठीक है:

String x = null;

यहाँ Stringअधिभार चुना गया है क्योंकि जावा संकलक सबसे विशिष्ट अधिभार उठाता है , जो कि JLS की धारा 15.12.2.5 के अनुसार है । विशेष रूप से:

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

अपने दूसरे मामले में, दोनों तरीकों अभी भी लागू होते हैं, लेकिन न तो Stringहै और न ही StringBufferअन्य की तुलना में अधिक सटीक है, इसलिए न तो विधि अन्य, इसलिए संकलक त्रुटि की तुलना में अधिक विशिष्ट है।


3
और स्ट्रिंग अधिभार वस्तु अधिभार की तुलना में अधिक विशिष्ट कैसे है?
14:16 पर user1610015

12
क्योंकि एक Objectकिसी भी प्रकार ले सकता है और इसे एक में लपेट सकता है Object, जबकि एक Stringकेवल एक ले सकता है String। इस मामले में, Stringप्रकार की तुलना में अधिक विशिष्ट है Object
जॉन

10
@zakSyed यदि आपसे पूछा गया कि क्या अधिक विशिष्ट "स्ट्रिंग" या "ऑब्जेक्ट" है, तो आप क्या कहेंगे? जाहिर है "स्ट्रिंग", सही? यदि आपसे पूछा गया: "स्ट्रिंग" या "स्ट्रिंगबफ़र" क्या अधिक विशिष्ट है? कोई जवाब नहीं है, वे दोनों ऑर्थोगोनल विशेषज्ञ हैं, आप उनके बीच कैसे चुन सकते हैं? तब आपको स्पष्ट होना चाहिए कि आप question.method((String)null)
किसके

1
@JonSkeet: यह समझ में आता है। इसलिए मूल रूप से यह सबसे विशिष्ट नियम के अनुसार एक विधि की तलाश करता है और अगर यह तय नहीं कर पाता है कि कौन सा अधिक विशिष्ट है तो यह एक संकलन-समय की त्रुटि को फेंक देगा।
zakSyed 15

3
@JonH "null" संदर्भ प्रकार है, यदि किसी एक विधि को पैरामीटर के रूप में एक आदिम प्रकार प्राप्त होता है (यानी int) तो यह संकलक द्वारा भी नहीं माना जाएगा जब प्रकार null के संदर्भ के लिए आह्वान करने के लिए सही विधि का चयन किया जाता है। यह भ्रामक है अगर "Int" से आपका मतलब java.lang.Integer से है या यदि आपका मतलब आदिम टाइप int से है।
एडविन डेलोरजो

9

इसके अतिरिक्त, JLS 3.10.7 भी घोषित करता है कि "null" "null प्रकार" का शाब्दिक मूल्य है। इसलिए "नल" नामक एक प्रकार मौजूद है।

बाद में, जेएलएस 4.1 बताता है कि एक अशक्त प्रकार मौजूद है, जिसमें चर घोषित करना असंभव है, लेकिन आप इसे केवल शून्य शाब्दिक माध्यम से उपयोग कर सकते हैं। बाद में यह कहता है:

अशक्त संदर्भ हमेशा किसी भी संदर्भ प्रकार में एक व्यापक संदर्भ रूपांतरण से गुजर सकता है।

कंपाइलर ने इसे चौड़ा करने का विकल्प क्यों चुना स्टिंग को जॉन के जवाब में अच्छी तरह से समझाया जा सकता है ।


मुझे पूरा यकीन है कि प्रकार शून्य है।
xavierm02

2
@ xavierm02 जावा भाषा विनिर्देश में इसका कोई उल्लेख नहीं है। क्या आप अपने संदर्भ का हवाला दे सकते हैं ताकि हम सभी आपके दावे को सत्यापित कर सकें?
एडविन डेलोरजो

मैंने वह बात कभी नहीं पढ़ी। लेकिन मैंने इस गर्मियों में कुछ जावा किया और आप एक वोड ऑब्जेक्ट लेने वाली विधि के साथ एक ऑब्जेक्ट को अधिभारित कर सकते हैं।
xavierm02

यह एक प्रकार से एक वर्ग से अधिक है।
xavierm02

4
@ xavierm02 बेशक आप कर सकते हैं। आप जावा में एक विधि को ओवरलोड कर सकते हैं जिसमें कोई अन्य प्रकार जो आप चाहते हैं। फिर भी, सवाल, या मेरे जवाब से कोई लेना-देना नहीं है।
एडविन डेलोरजो

2

आप stringकिसी nullमान को असाइन कर सकते हैं इसलिए यह मान्य है और जावा और अधिकांश प्रोग्रामिंग भाषाओं के लिए आदेश निकटतम प्रकार और फिर ऑब्जेक्ट के लिए फिट है।


2

शीर्षक में प्रश्न का उत्तर देने के लिए: nullन तो एक Stringऔर न ही एक है Object, लेकिन या तो एक संदर्भ सौंपा जा सकता है null

मैं वास्तव में आश्चर्यचकित हूं कि यह कोड भी संकलन करता है। मैंने पहले भी ऐसा ही कुछ करने की कोशिश की थी और मुझे यह कहते हुए एक कंपाइलर त्रुटि हुई कि कॉल अस्पष्ट था।

हालांकि, इस मामले में, ऐसा लगता है जैसे संकलक उस विधि को चुन रहा है जो खाद्य श्रृंखला पर सबसे कम है। यह मान रहा है कि आप इस विधि का कम से कम जेनेरिक संस्करण चाहते हैं ताकि आपको मदद मिल सके।

मुझे यह देखना होगा कि क्या मैं उस उदाहरण को खोद सकता हूं जहां मुझे इसमें एक संकलक त्रुटि मिली (प्रतीत होता है) ठीक उसी तरह का परिदृश्य, हालांकि ...]

संपादित करें: मैं देख रहा हूँ। मेरे द्वारा बनाए गए संस्करण में, मेरे पास एक Stringऔर एक को स्वीकार करने के दो अतिभारित तरीके थे Integer। इस परिदृश्य में, कोई "सबसे विशिष्ट" पैरामीटर (जैसा कि ) Objectऔर है String, इसलिए यह आपके कोड के विपरीत, उनके बीच चयन नहीं कर सकता है।

बहुत अच्छा सवाल!


अशक्त न तो है, लेकिन यह दोनों को सौंपा जा सकता है, यही अंतर है और यह संकलन करेगा कि यह क्यों नहीं होगा - यह बिल्कुल वैध कोड है।
जॉन

0

जैसा कि स्ट्रिंग प्रकार ऑब्जेक्ट प्रकार की तुलना में अधिक विशिष्ट है। मान लीजिए कि आप एक और विधि जोड़ते हैं जो एक इंटेगर प्रकार लेता है।

public void method(Integer i) {
      System.out.println("Integer Version");
   }

तब आपको यह कहते हुए एक कंपाइलर त्रुटि मिलेगी कि कॉल अस्पष्ट है। जैसा कि अब हम एक ही पूर्वता के साथ दो समान विशिष्ट तरीके हैं।


0

जावा कंपाइलर नल को असाइन करने के लिए सबसे व्युत्पन्न वर्ग प्रकार देता है।

इसे समझने के लिए यहाँ उदाहरण है:

class A{

    public void methodA(){
        System.out.println("Hello methodA");
    }
}

class B extends A{
    public void methodB(){
        System.out.println("Hello methodB");
    }
}

class C{
    public void methodC(){
        System.out.println("Hello methodC");
    }
}

public class MyTest {

     public static void fun(B Obj){
         System.out.println("B Class.");
     }
     public static void fun(A Obj){
         System.out.println("A Class.");
     }

    public static void main(String[] args) {
        fun(null);
    }
}

आउटपुट: बी क्लास।

दूसरी ओर:

public class MyTest {

     public static void fun(C Obj){
         System.out.println("B Class.");
     }
     public static void fun(A Obj){
         System.out.println("A Class.");
     }

    public static void main(String[] args) {
        fun(null);
    }
}

परिणाम: विधि का मजा (C) माइस्टेस्ट प्रकार के लिए अस्पष्ट है

आशा है कि यह इस मामले को बेहतर ढंग से समझने में मदद करेगा।


0

स्रोत: https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.2.5।
संकल्पना: सबसे विशिष्ट विधि
स्पष्टीकरण: यदि एक से अधिक सदस्य विधि दोनों सुलभ और एक विधि आह्वान पर लागू, रन-टाइम पद्धति प्रेषण के लिए विवरणक प्रदान करने के लिए किसी एक को चुनना आवश्यक है। जावा प्रोग्रामिंग भाषा उस नियम का उपयोग करती है जिसे सबसे विशिष्ट विधि चुना जाता है। नल को विशिष्ट प्रकार पर कास्टिंग करने का प्रयास करें और आप जिस विधि को चाहते हैं वह स्वचालित रूप से कॉल किया जाएगा।


पहले उदाहरण में, स्ट्रिंग ऑब्जेक्ट का विस्तार करता है, इसलिए "सबसे विशिष्ट" स्ट्रिंग को लेने की विधि है, लेकिन दूसरे उदाहरण में, स्ट्रिंग और स्ट्रिंगर दोनों ही ऑब्जेक्ट का विस्तार करते हैं, इसलिए वे समान रूप से विशिष्ट हैं और इसलिए संकलक एक विकल्प नहीं बना सकते हैं
डेविड केर

-1

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


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