software - java verify




एक गैर-अंतिम "स्थानीय" चर का उपयोग एक आंतरिक वर्ग के अंदर क्यों नहीं किया जा सकता है, और इसके बजाय संलग्नक वर्ग के गैर-अंतिम क्षेत्र में हो सकता है? (3)

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

अपडेट: जावा स्पेशलिस्ट्स न्यूज़लेटर # 25 इस पर अधिक विस्तार से चर्चा करता है।

यहां तक ​​कि संकलक त्रुटि मेरे लिए भ्रामक है। Cannot refer to a non-final variable message inside an inner class defined in a different method : क्या से अलग?

आंतरिक वर्ग की ' run पद्धति' से मेरा मानना ​​है।

संकलक त्रुटि पर स्टैक ओवरफ्लो पर कुछ विषय हैं Cannot refer to a non-final variable message inside an inner class defined in a different method और समाधान "इसे अंतिम घोषित करें और आप कर रहे हैं", लेकिन इस सैद्धांतिक प्रश्न के साथ मैं यह निरीक्षण करना चाहूंगा कि इस कोड को संकलित करने का तार्किक कारण क्या है:

private void updateStatus(String message) {
    Runnable doUpdateStatus = new Runnable() {
         public void run() {
             /* do something with message */
         }
    }
    /* do something with doUpdateStatus, like SwingUtilities.invokeLater() */
}

(समाधान: message को अंतिम घोषित करें) जबकि यह करता है:

private String enclosingClassField;
private void updateStatus() {
    Runnable doUpdateStatus = new Runnable() {
         public void run() {
             /* do something with enclosingClassField */
         }
    }
    /* do something with doUpdateStatus, like SwingUtilities.invokeLater() */
}

मैं वास्तव में उलझन में हूँ। enclosingClassField अंतिम नहीं है, यह हर बार कई बार बदल सकता है, जबकि updateStatus का खराब message तर्क केवल इसकी विधि निकाय के भीतर बदल सकता है, और इसके बजाय संकलक द्वारा दोषी ठहराया जाता है;)

यहां तक ​​कि संकलक त्रुटि मेरे लिए भ्रामक है। Cannot refer to a non-final variable message inside an inner class defined in a different method : क्या से अलग? क्या message को आंतरिक वर्ग के समान विधि में परिभाषित नहीं किया गया है? इसके बजाय enclosingClassField विधि के बाहर परिभाषित नहीं है? Uhm ...

क्या कोई मुझसे इस मामले की सही व्याख्या कर सकता है? धन्यवाद।


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

private String enclosingClassField;
private void updateStatus() {
    final MutableClass ms = new MutableClass(1, 2);
    Runnable doUpdateStatus = new Runnable() {
         public void run() {
             // you can use `EnclosingClass.this` because its is always final
             EnclosingClass.this.enclosingClassField = "";
             // shorthand for the previous line.
             enclosingClassField = "";
             // you cannot change `ms`, but you can change its mutable fields.
             ms.x = 3;
         }
    }
    /* do something with doUpdateStatus, like SwingUtilities.invokeLater() */
}

तीन प्रकार की चीजें: उदाहरण चर, स्थानीय चर और वस्तुएं:

■ Instance variables and objects live on the heap.
■ Local variables live on the stack.

आंतरिक वर्ग ऑब्जेक्ट उस विधि के स्थानीय चर का उपयोग नहीं कर सकता है जिसमें स्थानीय आंतरिक वर्ग परिभाषित है।

क्योंकि विधि के स्थानीय चर का उपयोग विधि के स्थानीय चर को स्टैक पर रखा जाता है और जैसे ही विधि समाप्त होती है वैसे ही खो जाती है।

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

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

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





java