2010-05-09 7 views
7

एक सरल सर्वर क्लासिक उदाहरण:विधियों में अंतिम परिवर्तनीय घोषणा का असर क्या है?

class ThreadPerTaskSocketServer { 
    public static void main(String[] args) throws IOException { 
     ServerSocket socket = new ServerSocket(80); 
     while (true) { 
      final Socket connection = socket.accept(); 
      Runnable task = new Runnable() { 
       public void run() { 
       handleRequest(connection); 
       } 
      }; 
      new Thread(task).start(); 
     } 
    } 
} 

क्यों Socketfinal के रूप में घोषित किया जाना चाहिए? क्या ऐसा इसलिए है क्योंकि नया Thread जो अनुरोध को संभालता है, विधि में socket चर को संदर्भित कर सकता है और ConcurrentModificationException के किसी प्रकार का कारण बन सकता है?

उत्तर

13

इस मामले में, चर अंतिम होना चाहिए गुमनाम Runnable implmentation अंदर इस्तेमाल किया जाएगा।

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

+0

बहुत बहुत धन्यवाद। – Finbarr

2

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

0

स्थानीय चर धागे के बीच साझा नहीं किए जाते हैं। (एक स्थानीय चर सक्रियण रिकॉर्ड का एक हिस्सा है, और प्रत्येक धागे का अपना सक्रियण रिकॉर्ड होता है)।

connection के बाद से, एक स्थानीय चर रहा है यह धागे के बीच साझा करने के लिए संभव नहीं है। चूंकि इसे धागे के बीच साझा नहीं किया गया है, इसलिए आपको इसे final बनाना होगा, इसलिए इससे कोई फर्क नहीं पड़ता कि यह एक स्थानीय चर है (इसे निरंतर मान की तरह देखा जा सकता है)।

0

यह ConcurrentModificationException को हल करने का इरादा नहीं है। विधि-नेस्टेड-क्लास (जैसे अज्ञात आंतरिक वर्ग) के अंदर उपयोग किए जाने वाले किसी भी स्थानीय चर को अंतिम के रूप में घोषित किया जाना चाहिए। पिछले सप्ताह यहां से एक ऐसी ही चर्चा देखें:

method local innerclasses accessing the local variables of the method

वास्तव में धागे के मामले में धागा सुरक्षा के लिए यहां एक छोटी सी योगदान है; धागे के बीच अंतिम चर पर कोई दृश्यता समस्या नहीं होगी। हालांकि, यह थ्रेड सुरक्षा की गारंटी नहीं देता है।

3

इस उदाहरण पर विचार:

class A { 
    B foo() { 
    final C c; 
    return new B() { 
     void goo() { 
     // do something with c 
     } 
    } 
    } 
} 
// somewhere else in the code 
A a = new A(); 
B b = a.foo(); 
b.goo(); 

तो ग था नहीं अंतिम, जब आप b.goo() तक पहुँचते हैं, यह, जंक को इंगित के बाद से कि सी कचरा-एकत्र हो सकता है - के अंत के बाद एक स्थानीय चर एक विधि कॉल

+0

क्या आप इंगित करते हैं कि अंतिम चर को कचरा-संग्रह नहीं मिलता है? वह झूठा है। – Pindatjuh

+0

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

+0

@ पिंडतुजू - मैं यह कह रहा हूं कि अंतिम चर को कचरा-कोलेटेड * नहीं मिलता है जब विधि समाप्त होती है *। @Eyal - आप ठीक है, भाषा बेहतर डिजाइन, आदि हालांकि, वर्तमान डिजाइन हमारे पास क्या है है हो सकता था कर रहे हैं ... –

2

एक विधि परिवर्तनीय अंतिम घोषित करने का अर्थ है कि इसका मूल्य बदल नहीं सकता है; कि यह केवल एक बार सेट किया जा सकता है। इस संदर्भ में यह कैसे लागू होता है?

मुझे कुछ समय के लिए अनाम कक्षाओं के साथ इस प्रतिबंध के बारे में पता है, लेकिन मुझे कभी समझ में नहीं आया कि क्यों। मैं देखता हूं कि अब तक कोई भी प्रतिक्रियाओं से वास्तव में कोई भी नहीं करता है। कुछ googling नीचे बदल गया जो मुझे लगता है कि यह समझाने का एक अच्छा काम करता है।

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

क्रेडिट करने के लिए: http://renaud.waldura.com/doc/java/final-keyword.shtml#vars

निश्चित रूप से स्पष्ट और कुछ मुझे लगता है कि कि संकलक वास्तव में डेवलपर्स से छुपा नहीं किया जाना चाहिए।

+0

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

+0

'एक विधि परिवर्तनीय अंतिम घोषित करने का अर्थ है कि इसका मूल्य बदल नहीं सकता है; कि यह केवल एक बार सेट किया जा सकता है। ज़रुरी नहीं। इसका मतलब है कि वस्तु के लिए ** संदर्भ ** बदला नहीं जा सकता है। मूल्य अभी भी कई बार बदला जा सकता है। (जब तक वस्तु एक आदिम नहीं है) – mercury0114

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