2012-11-20 12 views
7

के खिलाफ शिकायत ठीक है, इसलिए जहां तक ​​मुझे पता है, मैं इन चीजों को final चर के बारे में समझता हूं।अंतिम चर

  1. यह केवल एक बार
  2. सभी final चर सौंपा जाना चाहिए निर्माता से पहले प्रारंभ किया जाना चाहिए पूरा करता

अब ऊपर का उपयोग कर, मुझे समझ नहीं आता नीचे कैसे काम नहीं करता:

public class FinalTest implements AnotherClass { 

    private final Something something; 
    private final otherthing; 

    @Override 
    public void setStuff(Something something) { 
     this.something = something; 
     this.otherthing = new SomeClass(something); 
    } 

    public FinalTest(Something something) { 
     setStuff(something); 
    } 
} 

कन्स्ट्रक्टर final चर को पूरा करने से पहले यहां सेट किया जा रहा है। तो संकलक इसके खिलाफ शिकायत क्यों करता है?

+3

'अन्य चीज़' का प्रकार क्या है? – maerics

+2

यहां आपके लिए निश्चित असाइनमेंट पर जेएलएस अध्याय है। http://docs.oracle.com/javase/specs/jls/se7/html/jls-16.html आनंद लें। –

+1

अंतिम चर अच्छे हैं लेकिन कई बार वे समझ में नहीं आते हैं। यदि आपके पास अपनी कक्षा के भीतर से इसे सेट करने का कोई तरीका नहीं है, तो यह अभी भी "तर्कसंगत" अंतिम है, इसलिए इसे मजबूर करने पर भी लटका न लें। एक कन्स्ट्रक्टर (कक्षा वर्ग को खत्म करने के लिए ज़िम्मेदार) से एक विधि (जो आपकी कक्षा को एक पूर्ण राज्य में मानती है) को कॉल करने की वैधता पर भी विचार करें। यह देखभाल के साथ किया जाना चाहिए। –

उत्तर

18

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

भले ही आपने इसका उपयोग नहीं किया हो, लेकिन कंपाइलर इसके बारे में निश्चित नहीं हो सकता है, इसलिए यह इसकी अनुमति नहीं देता है। तकनीकी अवधि में, definite assignment नहीं है।

उदाहरण के लिए: -:

public static void main(String[] args) { 
    FinalTest obj = new FinalTest(something); 

    obj.setStuff(something); // There you go. This cannot be prevented. 
} 

इस पर विस्तृत विवरण के लिए JLS - Definite Assignments देखें - आप main से अपने वर्ग का दृष्टांत लगता है।

+0

+1 अच्छा स्पष्टीकरण :) – PermGenError

+0

@GanGnaMStYleOverFlowErroR .. धन्यवाद :) –

+4

यह स्पष्टीकरण समझ में नहीं आता है क्योंकि अगर मैं इसे निजी बनाता हूं तो मुझे इसे इस स्पष्टीकरण से करने की अनुमति देनी चाहिए। असली कारण यह है कि कोई निश्चित असाइनमेंट नहीं है। –

8

क्योंकि कोई भी ऑब्जेक्ट के जीवन में दूसरी बार setStuff() पर कॉल करने से आपको रोक नहीं रहा है, जो अवैध होगा।

final फ़ील्ड केवल कोड ब्लॉक में असाइन किए जा सकते हैं जिन्हें केवल एक बार चलाने की गारंटी है, जो कि रचनाकार और उदाहरण प्रारंभकर्ता हैं। (या static final फ़ील्ड के मामले में एक स्थिर प्रारंभिक।)

इस पर अधिक JLS में पाया जा सकता है।

+2

यह भी उल्लेखनीय है कि दो अलग-अलग राज्यों (शून्य और असाइन किए गए मान) में अंतिम चर का निरीक्षण करना संभव है यदि अंतिम को कन्स्ट्रक्टर में ओवरराइड करने योग्य विधि द्वारा एक्सेस किया जाता है (यही कारण है कि रचनाकारों को ओवरराइड करने योग्य तरीकों का कभी भी उपयोग नहीं करना चाहिए) – cfeduke

+0

@cfeduke वन कई कारणों से, हां। – biziclop

3

क्योंकि संकलक पता नहीं है कि केवल कॉल करने के लिए

public void setStuff(Something something) { 
    this.something = something; 
    this.otherthing = new SomeClass(something); 
} 

निम्न पंक्ति होना चाहिए निर्माता

0

से है

private final otherthing; 

कुछ की तरह

private final Something otherthing; 

आप कक्षा खो रहे हैं।

+0

प्रश्न –

0

बस एक ओर ध्यान दें:

@Override 
public void setStuff(Something something) { 
    this.something = something; 
    this.otherthing = new SomeClass(something); 
} 

public FinalTest(Something something) { 
    setStuff(something); 
} 

वास्तव में एक बुरा डिजाइन है कि। आपको कन्स्ट्रक्टर से एक अतिव्यापी विधि नहीं आनी चाहिए।

+0

को संबोधित नहीं करता है, मुझे पता है कि यह ठोस समस्या के लिए वास्तविक नहीं है। लेकिन मुझे लगता है कि यह एक अच्छी सलाह है। डाउनवोट क्यों? –

+0

क्योंकि यह कंक्रीट समस्या से संबंधित नहीं है –

+0

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

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