विधि मापदंडों और स्थानीय चरों के लिए किसी को अंतिम उपयोग कब करना चाहिए?


171

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

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

क्या यह ऐसा कुछ है जिसे मुझे याद रखने का प्रयास करना चाहिए?


यहाँ पर देखने के लिए एक संबंधित पोस्ट है: stackoverflow.com/questions/137868/…
मैटलेंट


1
मैं सिर्फ इसलिए अपवोट कर रहा हूं क्योंकि मुझे नहीं पता था कि इसे पढ़ने से पहले मापदंडों पर एक संशोधक के रूप में अंतिम उपयोग करना संभव था। धन्यवाद!
किप

जवाबों:


178

ग्रस्त रहना उसपर:

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

विचार करें लेकिन विवेकपूर्ण तरीके से उपयोग करें:

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

जब तक गुदा महसूस न हो तब तक अनदेखा करें:

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

  • संपादित करें: ध्यान दें कि एक उपयोग का मामला जहां अंतिम स्थानीय चर वास्तव में बहुत उपयोगी होते हैं, जैसा कि @ adam-gent द्वारा उल्लेख किया गया है जब मूल्य if/ elseशाखाओं में संस्करण को सौंपा जाता है ।


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

61
जोश बलोच (और यह एक काफी राशि है) के लिए सभी सम्मान के साथ, मैं सामान्य मामले के लिए असहमत हूं। एपीआई के निर्माण के मामले में, निश्चित रूप से चीजों को लॉक करें। अपने स्वयं के कोड के अंदर बुई, दीवारों को खड़ा करना जो आपको बाद में फाड़ना है, समय की बर्बादी है।
एलेक्स मिलर

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

9
IDEA में (आउट ऑफ द बॉक्स) सैकड़ों कोड निरीक्षण हैं, और उनमें से कुछ finalकक्षाओं / विधियों में अप्रयुक्त / अनावश्यक कोड का पता लगा सकते हैं । उदाहरण के लिए, यदि कोई अंतिम विधि एक चेक किए गए अपवाद को फेंकने की घोषणा करती है, लेकिन वास्तव में इसे फेंकता नहीं है, तो आईडिया आपको यह बताएगा, और आप throwsक्लॉज से अपवाद को हटा सकते हैं । कभी-कभी, आप अनुपयोगी पूरे तरीकों को भी ढूंढ सकते हैं, जो कि पता लगाने योग्य है जब उन्हें ओवरराइड नहीं किया जा सकता है।
रोजरियो

8
फाइनल के रूप में @rmaruszewski मार्किंग क्लासेस ज्यादातर मॉकिंग फ्रेमवर्क को मॉक करने में सक्षम बनाता है और इस प्रकार आपको टेस्ट करने के लिए कठिन कोड बनाता है। मैं केवल एक वर्ग फाइनल करूंगा अगर यह महत्वपूर्ण रूप से महत्वपूर्ण था कि इसे बढ़ाया नहीं जाए।
बजे माइक रायलैंडर

44

क्या यह कुछ ऐसा है जिसे करने के लिए मुझे याद रखने का प्रयास करना चाहिए?

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


3
सहेजें कार्रवाई के साथ महान टिप, उस के बारे में पता नहीं था।
पवित्रता

1
मैं मुख्य रूप से उस लाभ पर विचार कर रहा हूं, जो अंतिम रूप से किसी भी अनुकूलन के बजाय गलती से चर को गलत चर द्वारा कोड को सुरक्षित बनाता है, जो हो सकता है या नहीं हो सकता है।
पीटर हिल्टन

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

1
ग्रहण में उपयोगी टिप के लिए +1। मुझे लगता है कि हमें बग से बचने के लिए जितना संभव हो फाइनल उपयोग करना चाहिए।
पन्नाधाय

क्या आप इंटेलीज में भी ऐसा कर सकते हैं?
कोरे तुगे

15

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

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

एक चर "अंतिम" (और इसे निर्माता में असाइन करना) को चिह्नित करना निर्भरता इंजेक्शन के साथ उपयोगी है। यह चर के "सहयोगी" प्रकृति को इंगित करता है।

एक विधि "अंतिम" को चिह्नित करना अमूर्त वर्गों में उपयोगी है। यह स्पष्ट रूप से चित्रित करता है कि विस्तार बिंदु कहां हैं।


11

मैं finalजावा को अधिक अभिव्यक्ति आधारित बनाने के लिए हर समय उपयोग करता हूं । देखें जावा की स्थितियां ( if,else,switch) अभिव्यक्ति आधारित नहीं हैं, जो मुझे हमेशा से नफरत है, खासकर अगर आपके कार्यात्मक प्रोग्रामिंग (यानी एमएल, स्काला या लिस्प) के लिए उपयोग किया जाता है।

इस प्रकार आपको शर्तों का उपयोग करते समय हमेशा (IMHO) अंतिम चर का उपयोग करने का प्रयास करना चाहिए।

मैं आपको एक उदाहरण देता हूं:

    final String name;
    switch(pluginType) {
        case CANDIDATE_EXPORT:
            name = "Candidate Stuff";
            break;
        case JOB_POSTING_IMPORT:
            name = "Blah";
            break;
        default:
            throw new IllegalStateException();
    }

अब यदि कोई अन्य caseकथन जोड़ते हैं और सेट नहीं करते हैं nameतो संकलक विफल हो जाएगा। कंपाइलर भी विफल हो जाएगा यदि आप हर मामले पर नहीं तोड़ते हैं (कि आप चर सेट करते हैं)। यह आपको जावा को लिस्प के letअभिव्यक्तियों के समान बनाने की अनुमति देता है और इसे बनाता है ताकि आपका कोड बड़े पैमाने पर इंडेंट न हो (लेक्सिकल स्कूपिंग चर के कारण)।

और जैसा कि @Recurse ने उल्लेख किया है (लेकिन जाहिरा तौर पर -1) आप String name finalकंपाइलर त्रुटि (जो मैंने कभी नहीं कहा कि आप नहीं कर सकते थे) पाने के लिए पूर्ववर्ती कर सकते हैं, लेकिन आप आसानी से कंपाइलर त्रुटि को स्विच के बाद सेटिंग नाम से दूर कर सकते हैं वह कथन जो अभिव्यक्ति शब्दार्थ को फेंकता है या breakजिसे भूलकर आप एक त्रुटि का कारण नहीं बन सकते (जो @Recurse का उपयोग किए बिना कहता है) final:

    String name;
    switch(pluginType) {
        case CANDIDATE_EXPORT:
            name = "Candidate Stuff";
            //break; whoops forgot break.. 
            //this will cause a compile error for final ;P @Recurse
        case JOB_POSTING_IMPORT:
            name = "Blah";
            break;
    }
    // code, code, code
    // Below is not possible with final
    name = "Whoops bug";

बग सेटिंग नाम के कारण (इसके अलावा breakकिसी अन्य बग को भूल जाने के कारण ) अब मैं गलती से ऐसा कर सकता हूं:

    String name;
    switch(pluginType) {
        case CANDIDATE_EXPORT:
            name = "Candidate Stuff";
            break;
        //should have handled all the cases for pluginType
    }
    // code, code, code
    // Below is not possible with final
    name = "Whoops bug";

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

OCaml में ऊपर:

type plugin = CandidateExport | JobPostingImport

let p = CandidateExport

let name = match p with
    | CandidateExport -> "Candidate Stuff"
    | JobPostingImport -> "Blah" ;;

match ... with ...एक समारोह यानी अभिव्यक्ति की तरह मूल्यांकन करता है। ध्यान दें कि यह हमारे स्विच स्टेटमेंट की तरह कैसे दिखता है।

यहाँ स्कीम (रैकेट या चिकन) में एक उदाहरण दिया गया है:

(define name 
    (match b
      ['CandidateExport "Candidate Stuff"]
      ['JobPostingImport "Blah"]))

1
सिवाय इसके कि जावा कंपाइलर आपको पहले से ही "नाम संभावित रूप से असंगठित" त्रुटि देगा और फाइनल के साथ या इसके बिना संकलन करने से मना कर देगा।
जीवित करना

4
हां, लेकिन अंतिम के साथ आप इसे कभी भी रीसेट कर सकते हैं। मैंने वास्तव में ऐसा होता देखा है, जहां एक डेवलपर एक else if (...)में बदल गया if(...)और इस तरह चर को रीसेट कर रहा है। मैंने उसे दिखाया जो एक अंतिम चर के साथ कभी नहीं हुआ। मूल रूप से finalआपको चर को केवल एक बार और केवल एक बार असाइन करने के लिए मजबूर करता है ... इसलिए: P
एडम जेंट

9

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

फिर आप उपयोग किए गए बिंदु के करीब घोषित नए चर के साथ पुन: उपयोग किए गए चर को बदलकर कुछ त्रुटियों को ठीक कर सकते हैं। फिर आप पाते हैं कि आप विधि के पूरे हिस्सों को ब्रेसिंग में लपेट सकते हैं, और अचानक आप "एक्सट्रैक्ट मेथड" से दूर एक आईडीई कुंजी हो सकते हैं और आपका राक्षस बस अधिक समझ में आ गया।

अपने विधि है नहीं पहले से ही एक unmaintainable मलबे, मैं सामान यह कहा मलबे में तब्दील हो से लोगों को हतोत्साहित करने के लिए अंतिम बनाने में मूल्य हो सकता है लगता है; लेकिन अगर यह एक छोटा तरीका है (देखें: अचिन्त्य नहीं) तो आप बहुत अधिक वर्बोसिटी जोड़ने का जोखिम उठाते हैं। विशेष रूप से, जावा फ़ंक्शन हस्ताक्षर 80 वर्णों में फिट होने के लिए पर्याप्त कठिन हैं क्योंकि यह प्रति तर्क छह और जोड़ के बिना है!


1
बहुत वैध अंतिम बिंदु, हालांकि मैंने बहुत समय पहले 80 वर्णों की सीमा को छोड़ दिया था क्योंकि पिछले 10 वर्षों में स्क्रीन रिज़ॉल्यूशन थोड़ा बदल गया है। मैं आसानी से बिना स्क्रॉल किए अपनी स्क्रीन पर 300 चार लाइन लगा सकता हूं। फिर भी, finalहर पैरामीटर से पहले पठनीयता बेहतर है ।
ब्रांबोरियम

8

ठीक है, यह सब आपकी शैली पर निर्भर करता है ... यदि आप फाइनल को देखना पसंद करते हैं जब आप चर को संशोधित नहीं करेंगे, तो इसका उपयोग करें। यदि आप इसे देखना पसंद नहीं करते ... तो इसे छोड़ दें।

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

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

इसलिए, मैं कहूंगा कि जिस दिशा की ओर आप झुक रहे हैं, उसे उठाएं और बस उसके साथ जाएं (जो भी मामला हो, सुसंगत होने की कोशिश करें)।


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


6

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

 public int processSomethingCritical( final int x, final int y ){
 // hundreds of lines here 
     // for loop here...
         int x2 = 0;
        x++; // bug aarrgg...
 // hundreds of lines there
 // if( x == 0 ) { ...

 }

निश्चित रूप से एक आदर्श दुनिया में ऐसा नहीं होगा, लेकिन .. अच्छी तरह से .. कभी-कभी आपको दूसरों के कोड का समर्थन करना होगा। :(


2
इस पद्धति में अंतिम लापता होने की तुलना में अधिक गंभीर समस्याएं हैं। यह बहुत ही असामान्य है, हालांकि असंभव नहीं है, कि इस पद्धति का इतना अच्छा कारण है कि इस तरह की त्रुटियां हो सकती हैं। चर नामों में थोड़ा विचार इस तरह से दुर्घटनाओं की ओर एक लंबा रास्ता तय करेगा।
यकागनोविच 5

2
यदि आपके पास एक ही विधि में "कोड की सैकड़ों लाइनें" हैं, तो आप इसे कई छोटे तरीकों से तोड़ना चाहते हैं।
स्टीव कू

5

यदि आप एक आवेदन लिख रहे हैं कि किसी को 1 वर्ष के बाद, कोड को पढ़ना होगा, तो हाँ, चर पर अंतिम का उपयोग करें जिसे हर समय संशोधित नहीं किया जाना चाहिए। ऐसा करने से, आपका कोड अधिक "स्व-दस्तावेजीकरण" होगा और आप अन्य डेवलपर्स के लिए स्थानीय अस्थायी चर के रूप में स्थानीय स्थिरांक का उपयोग करने जैसी मूर्खतापूर्ण चीजें करने का मौका भी कम कर देंगे।

यदि आप कुछ फालतू कोड लिख रहे हैं, तो, nah, सभी स्थिरांक की पहचान करने और उन्हें अंतिम बनाने के लिए परेशान न करें।


4

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


2

यह इस प्रश्न से स्पष्ट नहीं है कि क्या यह स्पष्ट है, लेकिन एक विधि पैरामीटर को अंतिम बनाने से केवल विधि का शरीर प्रभावित होता है। यह करता है नहीं invoker को विधि के इरादों के बारे में कोई दिलचस्प जानकारी देना। में पारित किया जा रहा वस्तु अभी भी विधि (फाइनल नहीं है) के भीतर उत्परिवर्तित किया जा सकता है, और चर के दायरे विधि के भीतर है।

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

उदाहरण के लिए चर, मैं उन्हें अंतिम बनाऊंगा यदि वे तार्किक रूप से स्थिर हैं।


2

चर के लिए कई उपयोग हैं final। यहां महज कुछ हैं

अंतिम निरंतर

 public static class CircleToolsBetter {
     public final static double PI = 3.141;
        public double getCircleArea(final double radius) {
          return (Math.pow(radius, 2) * PI);
        }
    }

यह तब आपके कोड के अन्य हिस्सों के लिए उपयोग किया जा सकता है, या अन्य वर्गों द्वारा एक्सेस किया जा सकता है, इस तरह यदि आप कभी भी मूल्य बदलेंगे तो आपको उन्हें एक-एक करके बदलना नहीं पड़ेगा।

अंतिम चर

public static String someMethod(final String environmentKey) {
    final String key = "env." + environmentKey;
    System.out.println("Key is: " + key);
    return (System.getProperty(key));

  }

}

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

public class FinalVariables {


  public final static void main(final String[] args) {
    System.out.println("Note how the key variable is changed.");
    someMethod("JAVA_HOME");
    someMethod("ANT_HOME");
  }
}

अंतिम निरंतर

public double equation2Better(final double inputValue) {
    final double K = 1.414;
    final double X = 45.0;

double result = (((Math.pow(inputValue, 3.0d) * K) + X) * M);
double powInputValue = 0;         
if (result > 360) {
  powInputValue = X * Math.sin(result); 
} else {
  inputValue = K * Math.sin(result);   // <= Compiler error   
}

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

अंतिम संग्रह

अलग-अलग मामला जब हम कलेक्शंस की बात कर रहे हैं, तो आपको उन्हें एक अमोघ के रूप में स्थापित करने की आवश्यकता है।

 public final static Set VALID_COLORS; 
    static {
      Set temp = new HashSet( );
      temp.add(Color.red);
      temp.add(Color.orange);
      temp.add(Color.yellow);
      temp.add(Color.green);
      temp.add(Color.blue);
      temp.add(Color.decode("#4B0082")); // indigo
      temp.add(Color.decode("#8A2BE2")); // violet
      VALID_COLORS = Collections.unmodifiableSet(temp);
    }

अन्यथा, यदि आप इसे निर्धारित नहीं करते हैं:

Set colors = Rainbow.VALID_COLORS;
colors.add(Color.black); // <= logic error but allowed by compiler

अंतिम कक्षाओं और अंतिम विधियों को क्रमशः बढ़ाया या अधिलेखित नहीं किया जा सकता है।

संपादित करें: अंतिम कक्षा की नियुक्ति पंजीकरण प्रक्रिया का पता लगाने के लिए:

क्लास फाइनल करने के दो तरीके हैं। कक्षा घोषणा में कीवर्ड फाइनल का उपयोग करना सबसे पहले है:

public final class SomeClass {
  //  . . . Class contents
}

एक वर्ग फाइनल बनाने का दूसरा तरीका अपने सभी कंस्ट्रक्टरों को निजी घोषित करना है:

public class SomeClass {
  public final static SOME_INSTANCE = new SomeClass(5);
  private SomeClass(final int value) {
  }

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

public class Test{
  private Test(Class beanClass, Class stopClass, int flags)
    throws Exception{
    //  . . . snip . . . 
  }
}

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

इसलिए आपको इसे अंतिम रूप से तब चिन्हित करना चाहिए जब आप इसका निर्माण करने वाले को निजी बनाकर एक वर्ग फाइनल कर दें।


1

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


1

यदि आपके पास आंतरिक (अनाम) कक्षाएं हैं, और विधि को युक्त विधि के चर का उपयोग करने की आवश्यकता है, तो आपको उस चर को अंतिम रूप देना होगा।

इसके अलावा, आपने जो कहा है वह सही है।


अब java 8 प्रभावी अंतिम चर के साथ लचीलापन प्रदान करता है।
रवींद्र बाबू

0

finalयदि आप उस चर को बना रहे हैं तो एक चर के लिए कीवर्ड का उपयोग करेंimmutable

चर को अंतिम घोषित करते हुए, यह डेवलपर्स को बहु-थ्रेडेड वातावरण में चर के संभावित संशोधन मुद्दों को नियंत्रित करने के लिए सहायता करता है।

जावा 8 रिलीज के साथ, हमारे पास एक और अवधारणा है जिसे " effectively final variable" कहा जाता है । एक गैर-अंतिम चर अंतिम चर के रूप में गर्म हो सकता है।

लैम्ब्डा अभिव्यक्ति से संदर्भित स्थानीय चर अंतिम या प्रभावी रूप से अंतिम होने चाहिए

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

जावा 7 तक, आप एक अनाम वर्ग के अंदर एक गैर-अंतिम स्थानीय चर का उपयोग नहीं कर सकते, लेकिन जावा 8 से आप कर सकते हैं

इस लेख पर एक नज़र डालें


-1

सबसे पहले, चर को स्थिर बनाने के लिए अंतिम कीवर्ड का उपयोग किया जाता है। लगातार इसका मतलब है कि यह नहीं बदलता है। उदाहरण के लिए:

final int CM_PER_INCH = 2.54;

आप चर को अंतिम घोषित करेंगे क्योंकि एक सेंटीमीटर प्रति इंच नहीं बदलता है।

यदि आप अंतिम मान को ओवरराइड करने का प्रयास करते हैं, तो चर वह है जिसे पहले घोषित किया गया था। उदाहरण के लिए:

final String helloworld = "Hello World";
helloworld = "A String"; //helloworld still equals "Hello World"

एक संकलन त्रुटि है जो कुछ इस प्रकार है:

local variable is accessed from inner class, must be declared final

यदि आपके चर को अंतिम घोषित नहीं किया जा सकता है या यदि आप इसे अंतिम रूप से घोषित नहीं करना चाहते हैं तो यह कोशिश करें:

final String[] helloworld = new String[1];
helloworld[0] = "Hello World!";
System.out.println(helloworld[0]);
helloworld[0] = "A String";
System.out.println(helloworld[0]);

यह प्रिंट करेगा:

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