इंटरफ़ेस विधियों में अंतिम तर्क - बिंदु क्या है?


189

जावा में, finalइंटरफ़ेस विधियों में तर्कों को परिभाषित करना पूरी तरह से कानूनी है और इसे लागू करने वाले वर्ग में नहीं मानते हैं, जैसे:

public interface Foo {
    public void foo(int bar, final int baz);
}

public class FooImpl implements Foo {

    @Override
    public void foo(final int bar, int baz) {
        ...
    }
}

उपरोक्त उदाहरण में, barऔर bazइसके विपरीत हैfinal वर्ग वीएस इंटरफ़ेस में परिभाषाएं हैं।

एक ही तरीके से, किसी finalएक वर्ग विधि का दूसरे पर विस्तार होने पर कोई प्रतिबंध नहीं लगाया जाता हैabstract नहीं किया जाता है।

जबकि finalक्लास मेथड बॉडी के अंदर कुछ व्यावहारिक मूल्य है, क्या finalइंटरफ़ेस विधि मापदंडों के लिए कोई बिंदु निर्दिष्ट है ?


finalवैसे भी वे मूल रूप से कुछ भी नहीं करते हैं, क्योंकि वे कॉपी किए जाते हैं।
पॉल टॉम्बलिन

11
चर्चा के एक बिंदु के रूप में: मैंने अभी इसकी कोशिश की है और यदि दो interfaceपरिभाषाएँ केवल finalएक तर्क की विशेषता में भिन्न होती हैं , तो परिणामी .classफाइलें बाइट-फॉर-बाइट पहचान के रूप में होती हैं (और निश्चित रूप javap -vसे एक ही आउटपुट का उत्पादन करती हैं)। एक ही दो वर्गों के लिए सही है, जो केवल finalएक विशेषता पर भिन्न होते हैं , वैसे!
जोकिम सॉर

2
@Paul: यह संदर्भ के प्रकारों के साथ ठीक वैसा ही काम करता है: यह तर्कों को संशोधित होने पर रोकता है (यदि कार्यान्वयन में उपयोग किया जाता है)।
जोकिम सॉर

यह विधि हस्ताक्षर में जनता जितनी ही प्रासंगिकता है।
रॉबिन

2
@ दीपक: मैं आपको सभी प्रकार के प्रश्नों पर काम करने के उदाहरणों के लिए पूछ रहा हूँ, तब भी जब यह बहुत मायने नहीं रखता। मुझे लगता है कि आपको कुछ अमूर्त सोच सीखने की कोशिश करनी चाहिए: आपके सामने कुछ निष्पादन योग्य कोड होने पर एक समस्या के बारे में सोचने की कोशिश करें । यह लंबे समय में आपकी बहुत मदद करेगा।
जोकिम सॉर

जवाबों:


104

ऐसा लगता नहीं है कि इसका कोई मतलब है। जावा लैंग्वेज स्पेसिफिकेशन 4.12.4 के अनुसार :

एक वैरिएबल फाइनल घोषित करना उपयोगी प्रलेखन के रूप में काम कर सकता है कि इसका मूल्य नहीं बदलेगा और प्रोग्रामिंग त्रुटियों से बचने में मदद कर सकता है।

हालाँकि, ओवरराइड विधियों के हस्ताक्षरों के मिलान के लिएfinal एक विधि पैरामीटर पर एक संशोधक का उल्लेख नहीं किया गया है , और इसका कॉलर पर कोई प्रभाव नहीं पड़ता है, केवल एक कार्यान्वयन के निकाय के भीतर। इसके अलावा, जैसा कि रॉबिन ने एक टिप्पणी में कहा है, एक विधि पैरामीटर पर संशोधक उत्पन्न बाइट कोड पर कोई प्रभाव नहीं है। (यह अन्य उपयोगों के लिए सही नहीं है ।)finalfinal


क्या विधि पैरामीटर भी एक चर के रूप में योग्य है? यह स्पष्ट रूप से व्यवहार में है, लेकिन क्या यह विनिर्देश के संदर्भ में है?
मानस

11
इसका उपयोग हस्ताक्षरों से मिलान करने के लिए नहीं किया जा सकता है क्योंकि यह वास्तविक .class फ़ाइल में प्रकट नहीं होता है। यह केवल कंपाइलर के लिए है।
रोबिन

@mindas - JLS का कहना है कि चर सात प्रकार के होते हैं । विधि पैरामाटर सूची में चौथे स्थान पर हैं।
टेड होप

3
दस्तावेज़ीकरण बेकार के बगल में है, हालांकि, चूंकि finalसंशोधन लागू करने वाले वर्ग पर लागू नहीं किया गया है। आपका इंटरफ़ेस हस्ताक्षर केवल झूठ हो सकता है।
स्टीफन हैबरल

जावा 8 भाषा की युक्ति अब कहती है कि आठ प्रकार के चर हैं (सात में से - उन्होंने लैम्बडा मापदंडों को जोड़ा )। विधि पैरामीटर अभी भी सूची में चौथे हैं (जीवन में कम से कम कुछ चीजें स्थिर लगती हैं। :-))।
टेड हॉप

25

कुछ IDE अमूर्त / इंटरफ़ेस विधि के हस्ताक्षर की नकल करेंगे जब एक उप वर्ग में एक कार्यान्वयन विधि डालते हैं।

मेरा मानना ​​है कि यह संकलक के लिए कोई फर्क नहीं पड़ता है।

संपादित करें: जबकि मेरा मानना ​​है कि यह अतीत में सच था, मुझे नहीं लगता कि वर्तमान आईडीई इसे और अधिक करते हैं।


2
मान्य बिंदु, हालांकि मुझे नहीं लगता कि इस सुविधा के लागू होने पर (या गलती से छोड़ दिया गया था) कई आईडीई थे :-)
माइंडास

2
मुझे लगता है कि static transientखेतों की श्रेणी में है। ;)
पीटर लॉरी

1
और एक अमूर्त वर्ग पर सार्वजनिक निर्माणकर्ता।
पीटर लॉरी

1
इंटेलीज यह करता है। मेरा संस्करण IntelliJ IDEA 2016.1.3 बिल्ड # IU-145.1617 है।
छात्रावास

1
@ डॉर्महाउस, यह दिलचस्प है, क्योंकि एंड्रॉइड स्टूडियो (3.1.4 बिल्ड # AI-173.4907809) नहीं करता है :(
द गॉडफादर

18

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


6

अद्यतन: नीचे दिए गए मूल उत्तर को प्रश्न को पूरी तरह से समझे बिना लिखा गया था, और इसलिए यह सीधे प्रश्न को संबोधित नहीं करता है :)फिर भी, यह सामान्य उपयोग को समझने के इच्छुक लोगों के लिए जानकारीपूर्ण होना चाहिए।final कीवर्ड ।

प्रश्न के लिए, मैं अपनी टिप्पणी नीचे से उद्धृत करना चाहूंगा।

मेरा मानना ​​है कि आपको यह तय करने के लिए स्वतंत्र छोड़ने के तर्क की अंतिमता को लागू करने के लिए मजबूर नहीं किया जाना चाहिए कि क्या यह अंतिम होना चाहिए या अपने खुद के कार्यान्वयन में नहीं।

लेकिन हां, यह अजीब लगता है कि आप इसे finalइंटरफ़ेस में घोषित कर सकते हैं , लेकिन यह गैर-अंतिम है कार्यान्वयन में है। अगर यह या तो समझ में आता है:

ए। finalइंटरफ़ेस (अमूर्त) विधि तर्कों के लिए कीवर्ड की अनुमति नहीं थी (लेकिन आप इसे कार्यान्वयन में उपयोग कर सकते हैं), या
बी। finalइंटरफ़ेस में एक तर्क के रूप में घोषित करना इसे finalकार्यान्वयन में घोषित करने के लिए मजबूर करेगा (लेकिन गैर-फाइनल के लिए मजबूर नहीं)।


मैं दो कारणों के बारे में सोच सकता हूं कि एक विधि हस्ताक्षर में finalपैरामीटर क्यों हो सकते हैं : बीन्स और ऑब्जेक्ट्स ( वास्तव में, वे दोनों एक ही कारण हैं, लेकिन थोड़ा अलग संदर्भ हैं। )

वस्तुओं:

public static void main(String[] args) {
    StringBuilder cookingPot = new StringBuilder("Water ");
    addVegetables(cookingPot);
    addChicken(cookingPot);
    System.out.println(cookingPot.toString());
    // ^--- OUTPUT IS: Water Carrot Broccoli Chicken ChickenBroth 
    //      We forgot to add cauliflower. It went into the wrong pot.
}

private static void addVegetables(StringBuilder cookingPot) {
    cookingPot.append("Carrot ");
    cookingPot.append("Broccoli ");
    cookingPot = new StringBuilder(cookingPot.toString());
    //   ^--- Assignment allowed...
    cookingPot.append("Cauliflower ");
}

private static void addChicken(final StringBuilder cookingPot) {
    cookingPot.append("Chicken ");
    //cookingPot = new StringBuilder(cookingPot.toString());
    //     ^---- COMPILATION ERROR! It is final.
    cookingPot.append("ChickenBroth ");
}

finalकीवर्ड यह सुनिश्चित किया कि हम गलती से एक नया नहीं बनाएगा स्थानीय एक संकलन त्रुटि दिखा कर खाना पकाने के बर्तन जब हम ऐसा करने के लिए प्रयास किया। यह सुनिश्चित किया गया कि चिकन शोरबा हमारे मूल खाना पकाने के बर्तन में मिलाया जाए जो कि addChickenविधि को मिला। इसकी तुलना addVegetablesजहां हमने फूलगोभी को खो दिया है क्योंकि यह जोड़ा गया है कि मूल पॉट के बजाय एक नए स्थानीय खाना पकाने के बर्तन में मिला।

बीन्स: यह वस्तुओं के समान अवधारणा है (जैसा कि ऊपर दिखाया गया है) । बीन्स अनिवार्य रूप Objectसे जावा में हैं। हालांकि, सेम (JavaBeans) का उपयोग विभिन्न अनुप्रयोगों में संबंधित डेटा के परिभाषित संग्रह को संग्रहीत करने और पारित करने के लिए एक सुविधाजनक तरीके के रूप में किया जाता है। जिस तरह addVegetablesएक नया खाना पकाने के बर्तन बनाकर खाना पकाने की प्रक्रिया को गड़बड़ कर सकता है StringBuilderऔर फूलगोभी के साथ इसे फेंक सकता है, यह खाना पकाने के बर्तन जावाबीन के साथ भी कर सकता है ।


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

मेरा मानना है कि आप आप तय करने के लिए यह होना चाहिए मुक्त कर छोड़ने के लिए एक बहस के अंतिम लागू करने के लिए मजबूर नहीं कर रहे हैं अंतिम या अपने खुद के कार्यान्वयन में नहीं। लेकिन हां, यह अजीब लगता है कि आप इसे finalइंटरफ़ेस में घोषित कर सकते हैं , लेकिन कार्यान्वयन में यह गैर-अंतिम है। यदि इंटरफ़ेस (अमूर्त) विधि तर्कों के लिए या तो (ए) final कीवर्ड की अनुमति नहीं थी, तो यह अधिक समझ में आता होगा (लेकिन आप इसे कार्यान्वयन में उपयोग कर सकते हैं), या (बी)final इंटरफ़ेस में तर्क की घोषणा करते हुए इसे finalकार्यान्वयन में घोषित करने के लिए बाध्य करेंगे। (लेकिन गैर-फाइनल के लिए मजबूर नहीं)।
ADTC

"यह वास्तव में प्रश्न का सही उत्तर नहीं है" आप सही कह रहे हैं, मुझे नहीं पता कि मैं क्या सोच रहा था ... जुलाई के शुरुआती मूत घंटे या कुछ और होना चाहिए। :)
ADTC

2

मेरा मानना ​​है कि यह एक शानदार विवरण हो सकता है, क्योंकि यह अंतिम है या नहीं यह एक कार्यान्वयन विवरण है।

(एक इंटरफ़ेस में सार्वजनिक रूप से घोषित तरीकों / सदस्यों की तरह।)

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