java - आप जावा की @ ओवरराइड एनोटेशन का उपयोग कब करते हैं और क्यों?




annotations (18)

जावा की @ @Override एनोटेशन का उपयोग करने के लिए सबसे अच्छे प्रथाएं क्या हैं और क्यों?

ऐसा लगता है कि @ ओवरराइड एनोटेशन के साथ हर एक ओवरराइड विधि को चिह्नित करने के लिए यह अधिक होगा। क्या कुछ प्रोग्रामिंग स्थितियां हैं जो @Override और अन्य लोगों का उपयोग करने के लिए कॉल करती हैं जिन्हें कभी @Override उपयोग नहीं करना चाहिए?


@ @Override एनोटेशन का उपयोग एक सामान्य प्रोग्रामिंग गलती के खिलाफ एक संकलन-समय सुरक्षा के रूप में कार्य करता है। यदि आपके पास उस विधि पर एनोटेशन है जो आप वास्तव में सुपरक्लास विधि को ओवरराइड नहीं कर रहे हैं तो यह एक संकलन त्रुटि फेंक देगा।

सबसे आम मामला जहां यह उपयोगी होता है, जब आप बेस क्लास में एक अलग पैरामीटर सूची रखने के लिए एक विधि बदल रहे हैं। सुपरक्लास विधि को ओवरराइड करने के लिए उपयोग किए जाने वाले उप-वर्ग में एक विधि बदले गए विधि हस्ताक्षर के कारण ऐसा नहीं करेगी। यह कभी-कभी अजीब और अप्रत्याशित व्यवहार का कारण बन सकता है, खासकर जटिल विरासत संरचनाओं से निपटने पर। इसके खिलाफ @ @Override एनोटेशन सुरक्षा।


इंटरफेस पर @ ओवरराइड वास्तव में उपयोगी हैं, क्योंकि यदि आप इंटरफ़ेस बदलते हैं तो आपको चेतावनियां मिलेंगी।


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

सबसे पहले, यह संकलन समय पर " hashcode() " के बजाय " hashcode() " जैसी गलत वर्तनी पकड़ता है। यह डीबग करने के लिए परेशान हो सकता है कि आपकी विधि का नतीजा आपके कोड से मेल नहीं खाता है जब असली कारण यह है कि आपका कोड कभी नहीं बुलाया जाता है।

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


एक और चीज यह है कि कोड को पढ़ने पर यह और अधिक स्पष्ट हो जाता है कि यह अभिभावक वर्ग के व्यवहार को बदल रहा है। डीबगिंग में मदद कर सकते हैं।

इसके अलावा, जोशुआ ब्लॉक की पुस्तक इफेक्टिव जावा (द्वितीय संस्करण) में, आइटम 36 एनोटेशन के लाभों पर अधिक जानकारी देता है।


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


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


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

कुछ आईडीई, ग्रहण के रूप में, जावा 1.6 रनटाइम या उच्चतर के साथ भी कॉन्फ़िगर किया गया है, वे जावा 1.5 के अनुपालन को बनाए रखते हैं और उपरोक्त वर्णित @override के उपयोग की अनुमति नहीं देते हैं। उस व्यवहार से बचने के लिए आपको यहां जाना होगा: प्रोजेक्ट गुण -> जावा कंपाइलर -> "परियोजना विशिष्ट सेटिंग्स सक्षम करें" की जांच करें -> "कंपाइलर अनुपालन स्तर" = 6.0, या उच्चतर चुनें।

यदि आधार एक इंटरफ़ेस या कक्षा है, तो मैं हर बार इस विधि को स्वतंत्र रूप से ओवरराइड कर रहा हूं, इस एनोटेशन का उपयोग करना पसंद करता हूं।

यह आपको कुछ सामान्य त्रुटियों से परहेज करने में मदद करता है, जैसे कि जब आप सोच रहे हैं कि आप एक ईवेंट हैंडलर ओवरराइड कर रहे हैं और फिर आप कुछ भी नहीं देख रहे हैं। कल्पना करें कि आप कुछ यूआई घटक में इवेंट श्रोता जोड़ना चाहते हैं:

someUIComponent.addMouseListener(new MouseAdapter(){
  public void mouseEntered() {
     ...do something...
  }
});

उपर्युक्त कोड संकलित और चलाता है, लेकिन यदि आप माउस को कुछ यूआईसीओम्पोनेंट के अंदर ले जाते हैं तो "कुछ करें" कोड चलाएगा, क्योंकि वास्तव में आप आधार विधि mouseEntered(MouseEvent ev) ओवरराइड नहीं कर रहे हैं। आप बस एक नया पैरामीटर-कम विधि mouseEntered() । उस कोड के बजाए, यदि आपने @ @Override एनोटेशन का उपयोग किया है तो आपने संकलन त्रुटि देखी है और आप सोच रहे हैं कि आपका ईवेंट हैंडलर क्यों नहीं चल रहा था।


जब आप ओवरराइड कर रहे किसी विधि नाम पर गलत वर्तनी का उपयोग करते हैं तो यह आपको (अच्छी तरह से, कंपाइलर) पकड़ने की अनुमति देता है।


जब भी कोई विधि किसी अन्य विधि को ओवरराइड करता है, या कोई विधि किसी इंटरफ़ेस में हस्ताक्षर लागू करती है।

@ ओवरराइड एनोटेशन आपको आश्वासन देता है कि आपने वास्तव में कुछ ओवरराइड किया था। एनोटेशन के बिना आप गलत वर्तनी या पैरामीटर प्रकारों और संख्या में अंतर का जोखिम उठाते हैं।


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


मुझे लगता है कि यह एक संकलन-समय अनुस्मारक के रूप में सबसे उपयोगी है कि विधि का इरादा माता-पिता विधि को ओवरराइड करना है। उदहारण के लिए:

protected boolean displaySensitiveInformation() {
  return false;
}

आप अक्सर उपर्युक्त विधि की तरह कुछ देखेंगे जो बेस क्लास में एक विधि को ओवरराइड करता है। यह इस वर्ग का एक महत्वपूर्ण कार्यान्वयन विवरण है - हम संवेदनशील जानकारी को प्रदर्शित नहीं करना चाहते हैं।

मान लीजिए कि इस विधि को मूल वर्ग में बदल दिया गया है

protected boolean displaySensitiveInformation(Context context) {
  return true;
}

यह परिवर्तन किसी भी संकलन समय त्रुटियों या चेतावनियों का कारण नहीं बनता है - लेकिन यह सबक्लास के इच्छित व्यवहार को पूरी तरह बदल देता है।

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


मेरे लिए @ ओवरराइड मुझे सुनिश्चित करता है कि मेरे पास सही तरीके से हस्ताक्षर है। अगर मैं एनोटेशन डालता हूं और विधि सही ढंग से वर्तनी नहीं होती है, तो संकलक शिकायत करता है कि मुझे कुछ गलत है।


मैं हमेशा टैग का उपयोग करता हूं। यह छोटी गलतियों को पकड़ने के लिए एक सरल संकलन-समय झंडा है जो मैं कर सकता हूं।

यह toString() बजाय tostring() जैसी चीज़ों को पकड़ tostring()

छोटी चीजें बड़ी परियोजनाओं में मदद करती हैं।


मैं हर बार इसका इस्तेमाल करता हूं। यह एक और जानकारी है जिसे मैं जल्दी से समझने के लिए उपयोग कर सकता हूं कि जब मैं एक वर्ष में कोड का पुनरीक्षण करता हूं और मैं भूल गया हूं कि मैं पहली बार क्या सोच रहा था।


यहां कई अच्छे उत्तर हैं, इसलिए मुझे इसे देखने का एक और तरीका प्रदान करें ...

जब आप कोडिंग कर रहे हों तो कोई ओवरकिल नहीं है। @override टाइप करने के लिए आपको कुछ भी लागत नहीं है, लेकिन यदि आप किसी विधि का नाम गलत वर्तनी करते हैं या हस्ताक्षर थोड़ा गलत पाते हैं तो बचत बहुत अधिक हो सकती है।

इस बारे में इस बारे में सोचें: जब आपने यहां नेविगेट किया था और इस पोस्ट को टाइप किया था, तो आप अपने जीवन के बाकी हिस्सों के लिए @override टाइप करने से अधिक समय का अधिक इस्तेमाल करते थे; लेकिन यह एक त्रुटि से बचाता है जो आपको घंटे बचा सकता है।

यह सुनिश्चित करने के लिए जावा यह सब कुछ कर सकता है कि आपने संपादन / संकलन समय पर कोई गलती नहीं की है, यह व्यापक परीक्षण के बाहर किसी भी अन्य तरीके से रोकने योग्य गलतियों की पूरी कक्षा को हल करने का एक व्यावहारिक तरीका है।

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

एक और साफ प्रभाव यह है कि यदि आप एनोटेशन प्रदान नहीं करते हैं तो यह आपको संकलित समय पर चेतावनी देगा कि आपने गलती से एक मूल विधि को ओवरराइड किया है - कुछ ऐसा जो महत्वपूर्ण हो सकता है यदि आप ऐसा करने का इरादा नहीं रखते हैं।


सबसे अच्छा अभ्यास हमेशा इसका उपयोग करना है (या आईडीई उन्हें आपके लिए भरें)

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

उस तरह की सुरक्षा नेट हमेशा अच्छा है।


हर बार जब आप दो लाभों के लिए एक विधि को ओवरराइड करते हैं तो इसका इस्तेमाल करें। ऐसा करें ताकि आप यह सुनिश्चित करने के लिए कंपाइलर जांच का लाभ उठा सकें कि आप वास्तव में एक विधि को ओवरराइड कर रहे हैं जब आप सोचते हैं कि आप हैं। इस तरह, यदि आप एक विधि नाम गलत वर्तनी की गलत गलती करते हैं या पैरामीटर से सही ढंग से मेल नहीं खाते हैं, तो आपको चेतावनी दी जाएगी कि विधि वास्तव में ओवरराइड नहीं करती है जैसा आपको लगता है। दूसरा, यह आपके कोड को समझने में आसान बनाता है क्योंकि विधियों को ओवरराइट होने पर यह अधिक स्पष्ट होता है।

इसके अतिरिक्त, जावा 1.6 में जब आप एक ही लाभ के लिए एक इंटरफ़ेस लागू करते हैं तो आप इसे चिह्नित करने के लिए इसका उपयोग कर सकते हैं। मुझे लगता है कि अलग-अलग एनोटेशन (जैसे @Implements ) होना बेहतर होगा, लेकिन यह कुछ भी नहीं है।


इंटरफ़ेस कार्यान्वयन पर @ ओवरराइड असंगत है क्योंकि जावा में "इंटरफ़ेस ओवरराइडिंग" जैसी कोई चीज़ नहीं है।

@ इंटरफेस कार्यान्वयन पर ओवरराइड बेकार है क्योंकि अभ्यास में यह कोई भी बग नहीं पकड़ता है कि संकलन वैसे भी पकड़ नहीं पाएगा। केवल एक ही, दूरगामी परिदृश्य है जहां कार्यान्वयनकर्ताओं पर ओवरराइड वास्तव में कुछ करता है: यदि आप एक इंटरफ़ेस और इंटरफ़ेस रिमूव विधियों को लागू करते हैं, तो आपको संकलित समय पर अधिसूचित किया जाएगा कि आपको अप्रयुक्त कार्यान्वयन को हटा देना चाहिए। ध्यान दें कि यदि इंटरफ़ेस के नए संस्करण में नए या चेंज किए गए तरीके हैं तो आपको स्पष्ट रूप से एक संकलन त्रुटि मिल जाएगी क्योंकि आप नई सामग्री को लागू नहीं कर रहे हैं।

इंटरफ़ेस कार्यान्वयनकर्ताओं पर @ ओवरराइड को 1.6 में कभी अनुमति नहीं दी जानी चाहिए, और ग्रहण के साथ उदासीनता को डिफ़ॉल्ट व्यवहार के रूप में एनोटेशन डालने का चयन करना, हमें बहुत सारी अव्यवस्थित स्रोत फ़ाइलें मिलती हैं। 1.6 कोड पढ़ने पर, आप @ ओवरराइड एनोटेशन से नहीं देख सकते हैं यदि कोई विधि वास्तव में सुपरक्लास में किसी विधि को ओवरराइड करता है या केवल एक इंटरफ़ेस लागू करता है।

एक सुपरक्लास में वास्तव में एक विधि को ओवरराइड करते समय @ ओवरराइड का उपयोग करना ठीक है।






annotations