2009-03-04 40 views
39

अंदर अंतिम चर बनाने यह जावा में अनुमति दी है:एक पाश

for(int i=0;i<5;i++){ 
    final int myFinalVariable = i; 
} 

मेरे सवाल का कीवर्ड final है। क्या यह अंतिम चर करने की अनुमति है जो लूप के हर रन के साथ बदलता है? मैं यह सोच रहा था क्योंकि अंतिम कहता है कि आप चर के मान को नहीं बदल सकते (केवल myFinalVariable = i पर कॉल कर रहे हैं), लेकिन मैं पूरे चर को final int के साथ फिर से परिभाषित कर रहा हूं।

क्या वे एक ही नाम के साथ दो पूरी तरह से भिन्न चर हैं - लूप के पिछले भाग से चर के साथ पहले से ही कचरा कलेक्टर तक सड़क का नेतृत्व कर रहे हैं?

उत्तर

73

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

11

आप सही हैं, लूप में प्रत्येक पुनरावृत्ति के लिए, आप एक नया चर बना रहे हैं। चर समान नाम साझा करते हैं, लेकिन यह ठीक है क्योंकि वे एक ही दायरे में नहीं हैं। अगला उदाहरण नहीं काम होगा:

final int myFinalVariable = 0; 
for(int i=0;i<5;i++){ 
    myFinalVariable = i; 
} 
8

एक चर सिर्फ ढेर पर एक स्थान है। अपने वैरिएबल को जितना संभव हो उतना छोटा स्कोप रखें और उन्हें अंतिम बनाने की कोशिश करें। हालांकि स्कोप और फाइनल सिर्फ कोड कोड चीजें हैं ... एक कोड पीढ़ी/वीएम बिंदु से वे वास्तव में कोई फर्क नहीं पड़ता।

आपके विशिष्ट उदाहरण में, "int" का उपयोग करके कोई कचरा नहीं बनाया जाता है। हालांकि अगर यह वस्तुओं को बनाया जा रहा था तो दोनों मामलों के लिए कचरे की मात्रा और जब कचरा सफाई के लिए पात्र होगा, तो समान होगा।

public class X extends java.lang.Object{ 
public X(); 
    Code: 
    0: aload_0 
    1: invokespecial #1; //Method java/lang/Object."<init>":()V 
    4: return 

public static void main(java.lang.String[]); 
    Code: 
    0: invokestatic #2; //Method foo:()V 
    3: invokestatic #3; //Method bar:()V 
    6: return 

private static void foo(); 
    Code: 
    0: iconst_0 
    1: istore_0 
    2: iload_0 
    3: iconst_5 
    4: if_icmpge  15 
    7: iload_0 
    8: istore_1 
    9: iinc 0, 1 
    12: goto 2 
    15: return 

private static void bar(); 
    Code: 
    0: iconst_0 
    1: istore_0 
    2: iload_0 
    3: iconst_5 
    4: if_icmpge  15 
    7: iload_0 
    8: istore_1 
    9: iinc 0, 1 
    12: goto 2 
    15: return 

} 

किसी अन्य विधि घोषणा करता है कि पाश बाहर चर आप की वजह से थोड़ा अलग बाईटकोड देना जोड़ना:

public class X 
{ 
    public static void main(final String[] argv) 
    { 
     foo(); 
     bar(); 
    } 

    private static void foo() 
    { 
     for(int i=0;i<5;i++) 
     { 
      final int myFinalVariable = i; 
     } 
    } 

    private static void bar() 
    { 
     for(int i=0;i<5;i++) 
     { 
      int myFinalVariable = i; 
     } 
    } 
} 

संकलक प्रत्येक विधि के लिए समान बाईटकोड पैदा करता है:

निम्नलिखित कोड ले लो ऑर्डर करें कि चर घोषित किए गए हैं)। ध्यान दें कि इस संस्करण को चर अंतिम नहीं बनाया जा सकता है। इस अंतिम संस्करण का सबसे अच्छा तरीका नहीं है (पाश अंदर अंतिम चर सबसे अच्छा है अगर आप यह कर सकते):

private static void car() 
{ 
    int myFinalVariable; 

    for(int i=0;i<5;i++) 
    { 
     myFinalVariable = i; 
    } 
} 

private static void car(); 
    Code: 
    0: iconst_0 
    1: istore_1 
    2: iload_1 
    3: iconst_5 
    4: if_icmpge  15 
    7: iload_1 
    8: istore_0 
    9: iinc 1, 1 
    12: goto 2 
    15: return 

} 
2

जवाब के रूप में, हां, आप वाकई चर के रूप में एक पाश में चिह्नित कर सकते हैं 'अंतिम' । ऐसा करने का प्रभाव यहां है (जावा 7, एक्लिप्स इंडिगो, मैक ओएस एक्स शेर)।

for (int i = 0; i < 5; i++) { 

    // With 'final' you cannot assign a new value. 
    final int myFinalVariable = i; // Gets 0, 1, 2, 3, or 4 on each iteration. 
    myFinalVariable = 7; // Compiler error: The final local variable myFinalVariable cannot be assigned. 

    // Without 'final' you can assign a new value. 
    int myNotFinalVariable = i; // Gets 0, 1, 2, 3, or 4 on each iteration. 
    myNotFinalVariable = 7; // Compiler is OK with re-assignment of variable's value. 

} 
2

लूप के अंदर घोषित वैरिएबल में केवल लूप के एकल निष्पादन तक दायरा है।

लूप के अंदर चर के रूप में चर को घोषित करने से लूप के बीच चर के लिए कोई फर्क नहीं पड़ता है, लेकिन यदि हम अंतिम संशोधक के साथ लूप के बाहर चर को घोषित करते हैं तो संदर्भ चर के लिए आवंटित मूल प्रकार या ऑब्जेक्ट को आवंटित मान बदला नहीं जा सकता ।

नीचे दिए गए उदाहरण में पहले दो लूप के साथ कोई समस्या नहीं है, दोनों लूप एक ही आउटपुट देते हैं, लेकिन तीसरा पाश एक संकलन समय त्रुटि देता है।

सार्वजनिक कक्षा की परीक्षा {

public static void main(String[] args) { 
    for (int i = 0; i < 5; i++) { 
     final int j= i; 
     System.out.println(j); 
    } 
    for (int i = 0; i < 5; i++) { 
     int j= i; 
     System.out.println(j); 
    } 

    final int j; 
    for (int i = 0; i < 5; i++) { 
     j= i; 
     System.out.println(j); 
    } 
} 

}

कृपया मुझे सही कर अगर मैं गलत हूँ।