अंतिम के रूप में जावा विधि तर्क बनाना


92

finalनीचे दिए गए कोड के बीच क्या अंतर है । क्या तर्कों को घोषित करने में कोई फायदा है final

public String changeTimezone( Timestamp stamp, Timezone fTz, Timezone toTz){  
    return ....
}

public String changeTimezone(final Timestamp stamp, final Timezone fTz, 
        final Timezone toTz){
    return ....
}

4
कोड एनालाइज़र होते हैं जो चेतावनी देते हैं कि क्या कोई पैरामीटर फिर से उपयोग किया जाता है या फिर से असाइन किया गया है। (स्थानीय चरों के लिए भी समान) IMHO, यह ऐसे मापदंडों को पकड़ने का एक बेहतर तरीका है यदि आप बदलते उन्हें अवांछनीय पाते हैं।
पीटर लॉरी


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

जवाबों:


131

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

यह आपको विधि निकाय में एक और स्थानीय अंतिम चर घोषित करने से बचाता है:

 void m(final int param) {
        new Thread(new Runnable() {
            public void run() {
                System.err.println(param);
            }
        }).start();
    }

27
+1: यह एक महत्वपूर्ण उपयोग मामला है, और केवल समय जब आपको इसकी आवश्यकता होती है। (बाकी समय यह सिर्फ प्रोग्रामर की मदद करने के लिए सुविधाजनक होने की बात है।)
डोनल फेलो

3
क्या मैं इसके पीछे का कारण पूछ सकता हूं?
कोडवर्ड

21
जावा 8. के ​​साथ कोई और अधिक आवश्यक नहीं
अमित पाराशर

3
@simgineer यहाँ पढ़ें: stackoverflow.com/questions/28408109/…
पीटरम्यू

3
@AmitParashar ट्रू, लेकिन Java 8 आपको केवल कीवर्ड "फाइनल" का उपयोग करने से बचा रहा है, जब आपको हर बार एक आंतरिक वर्ग में चर का उपयोग करना होगा ... वास्तविकता यह है कि कंपाइलर केवल अंतिमता को अंतर्निहित कर रहा है, आप अभी भी चर को प्रभावी ढंग से अंतिम रूप देने की आवश्यकता है ... इसलिए, यदि आप बाद में इसे असाइन करने का प्रयास करते हैं, तो आपको अभी भी एक संकलन समय त्रुटि मिलती है! Java 8 : SNEAK 100 :)
varun

38

अंतिम कीवर्ड पर अंतिम शब्द से निकालें

अंतिम पैरामीटर

निम्नलिखित नमूना अंतिम पैरामीटर घोषित करता है:

public void doSomething(final int i, final int j)
{
  // cannot change the value of i or j here...
  // any change would be visible only inside the method...
}

फाइनल का उपयोग यहां किया गया है ताकि मैं यह सुनिश्चित कर सकूं कि दो इंडेक्स i और j गलती से विधि द्वारा रीसेट नहीं किए गए हैं। यह एक कपटी बग से बचाव का एक आसान तरीका है जो आपके मापदंडों के मूल्य को गलत तरीके से बदलता है। आम तौर पर, त्रुटियों के इस वर्ग से बचाने के लिए लघु विधियां एक बेहतर तरीका है, लेकिन अंतिम पैरामीटर आपकी कोडिंग शैली के लिए एक उपयोगी अतिरिक्त हो सकता है।

ध्यान दें कि अंतिम मापदंडों को विधि हस्ताक्षर का हिस्सा नहीं माना जाता है, और विधि कॉल को हल करते समय संकलक द्वारा अनदेखा किया जाता है। पैरामीटर को अंतिम घोषित किया जा सकता है (या नहीं) इस बात पर कोई प्रभाव नहीं है कि विधि कैसे ओवरराइड की जाती है।


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

27

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

मुझे स्वीकार करना चाहिए कि मैं शायद ही कभी मापदंडों के लिए अंतिम उपयोग करने के लिए याद करता हूं, शायद मुझे चाहिए।

public int example(final int basicRate){
    int discountRate;

    discountRate = basicRate - 10;
    // ... lots of code here 
    if ( isGoldCustomer ) {
        basicRate--;  // typo, we intended to say discountRate--, final catches this
    }
    // ... more code here

    return discountRate;
}

1
अंतिम के रूप में तर्कों को घोषित करने का शानदार उदाहरण उपयोगी हो सकता है। मैं इसके लिए आंशिक हूं लेकिन वे 3+ मापदंडों के लिए एक कौर हैं।
जोसहेड्ज़

14

इससे बहुत फर्क नहीं पड़ता। इसका मतलब सिर्फ इतना है कि आप नहीं लिख सकते हैं:

stamp = null;
fTz = new ...;

लेकिन आप अभी भी लिख सकते हैं:

stamp.setXXX(...);
fTz.setXXX(...);

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


3

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


1
मुझे कुछ जोड़ना है: यदि पैरामीटर आदिम हैं, तो मुझे कोई अंतर नहीं दिखता है। इसके अलावा, अगर पैरामीटर संग्रह (वस्तुओं की एक सूची है ...), अंतिम जोड़ने से उन्हें संशोधित होने से नहीं रोका जा सकता है।
सैम ००३

1
अपरिहार्यता हमेशा एक वांछनीय लक्षण है। जावा में यह बॉक्स से बाहर नहीं है। कम से कम चर को अंतिम बनाते हुए संदर्भ अखंडता सुनिश्चित करता है।
सिड

1
मैं सहमत हूँ। लेकिन अगर हम वास्तव में वस्तुओं के लिए अपरिवर्तनीयता प्राप्त करना चाहते हैं, तो हम एक गहरी क्लोन बनाने की कोशिश कर सकते हैं।
Sam003

2

इस पद्धति के निकाय के लिए finalकीवर्ड तर्क के संदर्भों को उन मामलों में संकलित त्रुटि देते हुए गलती से पुन: असाइन करने से रोकेगा (अधिकांश IDE सीधे शिकायत करेंगे)। कुछ लोग यह तर्क दे सकते हैं कि finalजब भी संभव हो सामान्य रूप से उपयोग करने से चीजों को गति मिलेगी लेकिन हाल के जेवीएम में ऐसा नहीं है।


2

दो फायदे जो मैं देख रहा हूं वे सूचीबद्ध हैं:

1 विधि तर्क को अंतिम के रूप में चिह्नित करना विधि के अंदर तर्क के पुनर्मिलन को रोकता है

आप उदाहरण से

    public String changeTimezone(final Timestamp stamp, final Timezone fTz, 
            final Timezone toTz){
    
    // THIS WILL CAUSE COMPILATION ERROR as fTz is marked as final argument

      fTz = Calendar.getInstance().getTimeZone();     
      return ..
    
    }

अंतिम के रूप में तर्कों को चिह्नित करने वाली एक जटिल विधि में इन तर्कों की आकस्मिक व्याख्या में मदद मिलेगी क्योंकि स्थानीय चर और संकलक के रूप में संकलक इन मामलों को ध्वजांकित करेंगे जैसा कि उदाहरण में दिखाया गया है।

2 अनाम आंतरिक वर्ग को तर्क पास करना

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


1

- अतीत में (जावा 8 :-) से पहले)

आंतरिक अनाम कक्षाओं के लिए विधि चर के "अंतिम" कीवर्ड प्रभावित पहुंच का उपयोग समझाएं।

- आधुनिक (जावा 8+) लेनगेज में ऐसे उपयोग की कोई आवश्यकता नहीं है:

जावा ने "प्रभावी रूप से अंतिम" चर पेश किए। यदि कोड चर के मूल्य को बदलने का अर्थ नहीं करता है, तो स्थानीय चर और विधि पैरामीटर अंतिम मान लिए जाते हैं। इसलिए यदि आप Java8 में ऐसा कोई कीवर्ड देखते हैं + तो आप मान सकते हैं कि यह आवश्यक है। "प्रभावी रूप से अंतिम" का परिचय हमें लैम्ब्डा का उपयोग करते समय कम कोड टाइप करता है।


0

जावा में इसका सिर्फ एक निर्माण है जो आपको एक अनुबंध को परिभाषित करने और इसे छड़ी करने में मदद करता है। इसी तरह की चर्चा यहाँ: http://c2.com/cgi/wiki?JavaFinalConsideredEvil

BTW - (जैसा कि ट्विकी कहते हैं), फाइनल के रूप में अंकन आम तौर पर निरर्थक है यदि आप अच्छे प्रोग्रामिंग सिद्धांतों का पालन कर रहे हैं और आने वाले तर्क संदर्भ को फिर से परिभाषित / पुन: परिभाषित करते हैं।

सबसे खराब स्थिति में, यदि आप आर्ग्स संदर्भ को पुनर्परिभाषित करते हैं, तो इसका फ़ंक्शन पर दिए गए वास्तविक मान को प्रभावित नहीं करने वाला है - क्योंकि केवल एक संदर्भ पारित किया गया था।


0

मैं सामान्य रूप से चर और फ़ील्ड को अंतिम रूप से चिह्नित करने की बात कर रहा हूं - केवल पद्धति के तर्क पर लागू नहीं होता है। (चिह्नित करने के तरीके / कक्षाएं अंतिम एक अलग चीज है)।

यह आपके कोड के पाठकों / भविष्य के अनुरक्षकों का पक्ष है। चर के एक समझदार नाम के साथ, यह आपके कोड के पाठक को यह देखने और समझने में सहायक और आश्वस्त करता है कि प्रश्न में चर क्या दर्शाते हैं - और यह पाठक को आश्वस्त करता है कि जब भी आप चर को उसी दायरे में देखते हैं, तो अर्थ ठहर जाता है वही, इसलिए उसे हर संदर्भ में एक चर का क्या मतलब है यह जानने के लिए अपने सिर को खरोंचने की ज़रूरत नहीं है। हमने चर के "पुन: उपयोग" के बहुत सारे दुरुपयोग देखे हैं, जो समझने के लिए एक छोटे कोड को भी कठिन बना देता है।


-3

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

मान लीजिए हमारे पास एक तरीका है

Method1 () {

दिनांक dateOfBirth = नई तिथि ("1/1/2009");

Method2 (dateOfBirth);

method3 (dateOfBirth); }

सार्वजनिक mehod2 (तिथि dateOfBirth) {
....
....
....
}

सार्वजनिक mehod2 (दिनांक dateOfBirth) {
....
....
....
}

उपरोक्त मामले में अगर "dateOfBirth" को मेथड 2 में नया मान दिया गया है तो इससे मेथड 3 से गलत आउटपुट प्राप्त होगा। जैसे मान जो मेथड 3 में पास किया जा रहा है वह वैसा नहीं है जैसा मेथड 2 में पास होने से पहले था। इसलिए इस अंतिम कीवर्ड से बचने के लिए मापदंडों का उपयोग किया जाता है।

और यह जावा कोडिंग बेस्ट प्रैक्टिस में से एक भी है।


5
यह बिल्कुल सही नहीं है। भले ही तर्क dateOfBirth मेथड 2 में दूसरे मान में बदल जाए () यह मेथड 2 () पर कोई प्रभाव नहीं डालेगा, क्योंकि जावा वैल्यू से गुजरता है और संदर्भ से नहीं।
फ़्लो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.