2008-11-26 30 views
85

कल मेरे पास दो घंटे का तकनीकी फोन साक्षात्कार था (जिसे मैंने पास किया, woohoo!), लेकिन मैंने जावा में गतिशील बाध्यकारी के संबंध में निम्नलिखित प्रश्नों को पूरी तरह से मफ किया। और यह दोगुना परेशान है क्योंकि मैं कुछ साल पहले टीए था जब मैं इस अवधारणा को स्नातक के लिए पढ़ाना चाहता था, इसलिए संभावना है कि मैंने उन्हें गलत जानकारी दी है ...जावा गतिशील बाध्यकारी और विधि ओवरराइडिंग

यहां दी गई समस्या है:

/* What is the output of the following program? */ 

public class Test { 

    public boolean equals(Test other) { 
    System.out.println("Inside of Test.equals"); 
    return false; 
    } 

    public static void main(String [] args) { 
    Object t1 = new Test(); 
    Object t2 = new Test(); 
    Test t3 = new Test(); 
    Object o1 = new Object(); 

    int count = 0; 
    System.out.println(count++);// prints 0 
    t1.equals(t2) ; 
    System.out.println(count++);// prints 1 
    t1.equals(t3); 
    System.out.println(count++);// prints 2 
    t3.equals(o1); 
    System.out.println(count++);// prints 3 
    t3.equals(t3); 
    System.out.println(count++);// prints 4 
    t3.equals(t2); 
    } 
} 

मैं ने कहा कि उत्पादन ओवरराइड equals() विधि के भीतर से दो अलग-अलग प्रिंट बयान किया जाना चाहिए था: t1.equals(t3) और t3.equals(t3) पर। बाद वाला मामला पर्याप्त स्पष्ट है, और पूर्व मामले के साथ, भले ही t1 में ऑब्जेक्ट का एक संदर्भ है, इसे टाइप टेस्ट के रूप में तत्काल किया जाता है, इसलिए गतिशील बाध्यकारी विधि के ओवरराइड फॉर्म को कॉल करना चाहिए।

स्पष्ट रूप से नहीं। मेरे साक्षात्कारकर्ता ने मुझे प्रोग्राम चलाने के लिए प्रोत्साहित किया, और देखो और देखें, ओवरराइड विधि से केवल एक ही आउटपुट था: लाइन t3.equals(t3) पर।

मेरा प्रश्न तब है, क्यों? जैसा कि मैंने पहले ही उल्लेख किया है, भले ही t1 ऑब्जेक्ट का एक संदर्भ है (इसलिए स्थिर बाध्यकारी ऑब्जेक्ट की equals() विधि का आह्वान करेगा), गतिशील बाध्यकारी संदर्भ के तत्काल प्रकार के आधार पर विधि के सबसे विशिष्ट संस्करण को आविष्कार करने का ख्याल रखना चाहिए। मैं क्या खो रहा हूँ?

+0

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

उत्तर

78

जावा अतिभारित तरीकों के लिए बाध्यकारी स्थिर का उपयोग करता है, और ओवरराइड लोगों के लिए गतिशील बंधन। अपने उदाहरण में, बराबरी विधि ओवरलोड हो गया है (Object.equals तुलना में एक अलग परम प्रकार है()), तो विधि कहा जाता संकलन समय पर संदर्भ प्रकार के लिए बाध्य है।

कुछ चर्चा here

तथ्य यह है कि यह बराबरी विधि वास्तव में प्रासंगिक नहीं है अन्य है, की तुलना में यह यह ओवरराइड के बजाय ओवरलोड है, जो आप करने के लिए अपने उत्तर के आधार पर की पहले से ही जानते हैं एक आम गलती है साक्षात्कार में समस्या।

संपादित करें: एक अच्छा वर्णन here भी। यह उदाहरण इसके बजाय पैरामीटर प्रकार से संबंधित एक समान समस्या दिखा रहा है, लेकिन एक ही समस्या के कारण होता है।

मेरा मानना ​​है कि अगर बंधन वास्तव में गतिशील थे, तो किसी भी मामले में जहां फोन करने वाले और पैरामीटर थे टेस्ट का एक उदाहरण ओवरराइड विधि में परिणाम होगा बुलाया जा रहा है। तो t3.equals (o1) एकमात्र ऐसा मामला होगा जो प्रिंट नहीं करेगा।

+0

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

+4

मेरी गलती पूरी तरह से इस तथ्य को याद कर रही थी कि विधि वास्तव में ओवरराइड की बजाय ओवरलोड हो गई है। मैंने "बराबर()" देखा और तुरंत विरासत में और अतिरंजित सोचा। ऐसा लगता है कि, फिर भी, व्यापक और अधिक कठिन अवधारणा को सही मिला, लेकिन सरल विवरण खराब कर दिया। : पी – Magsol

+14

एक अन्य कारण @Override एनोटेशन मौजूद है। – Matt

4

मुझे लगता है कि कुंजी इस तथ्य में निहित है कि बराबर() विधि मानक के अनुरूप नहीं है: यह किसी अन्य टेस्ट ऑब्जेक्ट में ले जाती है, ऑब्जेक्ट ऑब्जेक्ट नहीं और इस प्रकार बराबर() विधि को ओवरराइड नहीं कर रही है। इसका मतलब यह है कि आपने वास्तव में इसे कुछ विशेष करने के लिए केवल अधिभारित किया है जब इसे ऑब्जेक्ट ऑब्जेक्ट देने के दौरान ऑब्जेक्ट ऑब्जेक्ट को ऑब्जेक्ट ऑब्जेक्ट्स ऑब्जेक्ट .equals (ऑब्जेक्ट ओ) कहते हैं। किसी भी आईडीई के माध्यम से कोड को देखना आपको टेस्ट के लिए दो बराबर() विधियों को दिखाना चाहिए।

+0

यह, और अधिकांश प्रतिक्रियाओं में बिंदु गुम है। मुद्दा इस तथ्य के बारे में नहीं है कि अधिभार के बजाय ओवरलोडिंग का उपयोग किया जा रहा है। यही कारण है कि t1.equals (t3) के लिए उपयोग की जाने वाली अधिभारित विधि नहीं है, जब टी 1 को ऑब्जेक्ट के रूप में घोषित किया जाता है लेकिन परीक्षण में आरंभ किया जाता है। – Robin

4

विधि अतिरंजित के बजाय अधिभारित है। बराबर हमेशा ऑब्जेक्ट पैरामीटर के रूप में लेते हैं।

बीटीडब्ल्यू, आपके पास ब्लोच के प्रभावी जावा (जो आपके पास होना चाहिए) में इस पर एक वस्तु है।

+0

जोशुआ ब्लोच का प्रभावी जावा? – DJClayworth

+0

प्रभावी हाँ, लिखते समय कुछ और सोच रहा था: डी – Gilles

25

Test की equals विधि java.lang.Object की equals विधि हावी नहीं होता। पैरामीटर प्रकार को देखो! Test कक्षा equals को एक विधि के साथ अधिभारित कर रही है जो Test स्वीकार करती है।

यदि equals विधि ओवरराइड करने का इरादा है, तो इसे @ ओवरराइड एनोटेशन का उपयोग करना चाहिए। यह इस सामान्य गलती को इंगित करने के लिए एक संकलन त्रुटि का कारण बन जाएगा।

+0

हाँ, मुझे पूरा यकीन नहीं है कि मुझे यह सरल लेकिन महत्वपूर्ण विवरण क्यों याद आया, लेकिन यह वही है जहां मेरी समस्या थी। धन्यवाद! – Magsol

+0

प्रश्नकर्ता के उत्सुक परिणामों के सही जवाब होने के लिए –

+0

कृपया इस पोस्ट पर मेरी पोस्ट पाएं जहां मैंने अतिरिक्त मामलों के साथ व्याख्या करने के लिए अपनी पूरी कोशिश की है। मैं वास्तव में आपके इनपुट की सराहना करता हूं :) –

5

जावा पैरामीटर में सह-भिन्नता का समर्थन नहीं करता है, केवल वापसी प्रकारों में।

दूसरे शब्दों में, जबकि ओवरराइडिंग विधि में आपका रिटर्न टाइप ओवरराइड में क्या था, इसका सबटाइप हो सकता है, यह पैरामीटर के लिए सही नहीं है।

यदि ऑब्जेक्ट में बराबर के लिए आपका पैरामीटर ऑब्जेक्ट है, तो उप-वर्ग में किसी और चीज के साथ बराबर डालना एक अतिरंजित विधि नहीं होगा, एक ओवरराइड विधि नहीं। इसलिए, एकमात्र ऐसी स्थिति जहां उस विधि को बुलाया जाएगा, जब पैरामीटर का स्थिर प्रकार टेस्ट होता है, जैसा कि टी 3 के मामले में होता है।

नौकरी साक्षात्कार प्रक्रिया के साथ शुभकामनाएं!मैं एक कंपनी है कि बजाय हमेशा की तरह algo/डाटा संरचनाओं सवाल है कि मैं अपने छात्रों को पढ़ाने के सवालों के इन प्रकार पूछता है पर इंटरव्यू देना अच्छा लगेगा।

+1

आपका मतलब contravariant पैरामीटर है। –

+0

मैं किसी भी तरह से इस तथ्य पर पूरी तरह से चमक गया कि विभिन्न विधि पैरामीटर आंतरिक रूप से ओवरलोडेड विधि बनाते हैं, एक ओवरराइड नहीं। ओह चिंता न करें, अलगो/डेटा संरचना प्रश्न भी थे। : पी और शुभकामना के लिए धन्यवाद, मुझे इसकी आवश्यकता होगी! :) – Magsol

6

दिलचस्प बात यह ग्रूवी कोड (जो एक वर्ग फ़ाइल को संकलित किया जा सकता है) में, सभी कॉल्स में से एक है, लेकिन प्रिंट बयान पर अमल होगा। (एक एक वस्तु के लिए एक टेस्ट की तुलना में स्पष्ट रूप से Test.equals (टेस्ट) फ़ंक्शन को कॉल नहीं होंगे।) यह है है क्योंकि ग्रूवी पूरी तरह से गतिशील टाइपिंग करते हैं। यह विशेष रूप से ब्याज की वजह से है क्योंकि इसमें कोई चर नहीं है जो स्पष्ट रूप से गतिशील रूप से टाइप किए गए हैं। मैंने कुछ स्थानों में पढ़ा है कि इसे हानिकारक माना जाता है, क्योंकि प्रोग्रामर जावा चीज़ करने के लिए ग्रोवी की अपेक्षा करते हैं।

+0

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

+0

जेडीके 7 में invokedynamic के साथ अच्छा और तेज़ होना चाहिए (या आज भी इसी तरह की कार्यान्वयन तकनीक का उपयोग करना)। –

0

सवाल का जवाब "क्यों?" इस प्रकार जावा भाषा परिभाषित की गई है।

के शब्दों में Wikipedia article on Covariance and Contravariance:

वापसी प्रकार सहप्रसरण जावा प्रोग्रामिंग भाषा संस्करण J2SE 5.0 में कार्यान्वित किया जाता है। पैरामीटर प्रकार, विधि अधिभावी के लिए बिल्कुल वैसा ही (अपरिवर्तनीय) होने के लिए है अन्यथा विधि के बजाय एक समानांतर परिभाषा के साथ ओवरलोड हो गया है।

अन्य भाषाओं अलग हैं।

+0

मेरी समस्या लगभग 3 + 3 और 9 लिखने के बराबर थी, फिर 1 + 1 और 2 लिखना।मैं समझता हूं कि जावा भाषा कैसे परिभाषित की जाती है; इस मामले में, किसी भी कारण से, मैंने पूरी तरह से उस चीज़ के लिए विधि को गलत तरीके से गलत नहीं किया, भले ही मैंने उसी समस्या में कहीं और उस गलती से परहेज किया। – Magsol

0

यह बहुत स्पष्ट है, यहाँ अधिभावी की कोई अवधारणा नहीं है। यह विधि ओवरलोडिंग है। वस्तु वर्ग के Object() विधि प्रकार वस्तु के संदर्भ के पैरामीटर लेता है और इस equal() विधि प्रकार टेस्ट के संदर्भ के पैरामीटर लेता है।

4

गतिशील में कुछ टिप्पणी बाइंडिंग (डीडी) और स्टेटिक बाध्यकारी (एसबी) थोड़ी देर के खोज के बाद:

1.Timing निष्पादित: (Ref।1)

  • डीबी: संकलक समय

के 2.Used:

  • डीबी: अधिभावी
  • एस.बी.: अधिक भार (स्थिर रन टाइम
  • एस.बी. पर , निजी, अंतिम) (Ref.2)

संदर्भ:

  1. मतलब समाधानकर्ता जो विधि क्योंकि संशोधक के साथ विधि अधिभावी नहीं कर सकते, स्थिर निजी या अंतिम
  2. http://javarevisited.blogspot.com/2012/03/what-is-static-and-dynamic-binding-in.html
1

मैं एक दिलचस्प पाया

  • का उपयोग करना पसंद निष्पादित गतिशील बनाम स्थिर बाध्यकारी के बारे में लेख। यह गतिशील बाध्यकारी अनुकरण के लिए कोड के एक टुकड़े के साथ आता है। यह मेरे कोड को और अधिक पठनीय बना दिया।

    https://sites.google.com/site/jeffhartkopf/covariance

  • 2

    तो किसी अन्य विधि जोड़ा जाता है कि बजाय यह अधिक भार रन टाइम पर गतिशील बंधन कॉल की व्याख्या करेगा की ओवरराइड करता है।

    /* निम्नलिखित प्रोग्राम का आउटपुट क्या है? */

    public class DynamicBinding { 
        public boolean equals(Test other) { 
         System.out.println("Inside of Test.equals"); 
         return false; 
        } 
    
        @Override 
        public boolean equals(Object other) { 
         System.out.println("Inside @override: this is dynamic binding"); 
         return false; 
        } 
    
        public static void main(String[] args) { 
         Object t1 = new Test(); 
         Object t2 = new Test(); 
         Test t3 = new Test(); 
         Object o1 = new Object(); 
    
         int count = 0; 
         System.out.println(count++);// prints 0 
         t1.equals(t2); 
         System.out.println(count++);// prints 1 
         t1.equals(t3); 
         System.out.println(count++);// prints 2 
         t3.equals(o1); 
         System.out.println(count++);// prints 3 
         t3.equals(t3); 
         System.out.println(count++);// prints 4 
         t3.equals(t2); 
        } 
    } 
    
    -1

    मैं दो उदाहरणों के माध्यम से इसे समझाने की कोशिश करूंगा जो कुछ उदाहरणों के विस्तारित संस्करण हैं जो मैं ऑनलाइन भर में आया था।

    public class Test { 
    
        public boolean equals(Test other) { 
         System.out.println("Inside of Test.equals"); 
         return false; 
        } 
    
        @Override 
        public boolean equals(Object other) { 
         System.out.println("Inside of Test.equals ot type Object"); 
         return false; 
        } 
    
        public static void main(String[] args) { 
         Object t1 = new Test(); 
         Object t2 = new Test(); 
         Test t3 = new Test(); 
         Object o1 = new Object(); 
    
         int count = 0; 
         System.out.println(count++); // prints 0 
         o1.equals(t2); 
    
         System.out.println("\n" + count++); // prints 1 
         o1.equals(t3); 
    
         System.out.println("\n" + count++);// prints 2 
         t1.equals(t2); 
    
         System.out.println("\n" + count++);// prints 3 
         t1.equals(t3); 
    
         System.out.println("\n" + count++);// prints 4 
         t3.equals(o1); 
    
         System.out.println("\n" + count++);// prints 5 
         t3.equals(t3); 
    
         System.out.println("\n" + count++);// prints 6 
         t3.equals(t2); 
        } 
    } 
    

    यहां, गिनती मान 0, 1, 2, और 3 के साथ लाइनों के लिए; हम संदर्भ O1 और equals() पद्धति पर t1 के लिए कीवस्तु है। इस प्रकार, संकलन समय पर, से equals() विधि ऑब्जेक्ट.क्लास फ़ाइल बाध्य होगी।

    हालांकि, यहां तक ​​हालांकि संदर्भ की t1वस्तु है, यह intialization टेस्ट वर्ग की है।
    Object t1 = new Test();
    इसलिए, रन-टाइम में यह public boolean equals(Object other) जो एक

    ओवरराइड विधि

    है कहता है। enter image description here

    अब, 4 और 6 के रूप में गिनती मूल्यों के लिए, यह फिर से स्पष्ट है कि t3 जो संदर्भ और प्रारंभ टेस्ट के वस्तु संदर्भ के रूप में पैरामीटर के साथ equals() विधि बुला रहा है है और एक

    है

    विधि

    ठीक अतिभारित!

    फिर से, बेहतर समझने के लिए क्या विधि संकलक, कॉल करेंगे पद्धति पर सिर्फ क्लिक करें और ग्रहण जो यह सोचता है कि संकलन समय पर फोन करेगा समान प्रकार के तरीकों पर प्रकाश डाला जाएगा। अगर इसे संकलित समय पर नहीं मिला है तो उन विधियों विधि ओवरराइडिंग का एक उदाहरण हैं।

    enter image description here

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

    • कोई संबंधित समस्या नहीं^_^