क्या जावा में चर के लिए अंतिम उपयोग करने से कचरा संग्रह में सुधार होता है?


86

आज मेरे सहयोगियों और मेरे पास finalकचरा संग्रह में सुधार करने के लिए जावा में कीवर्ड के उपयोग के बारे में चर्चा है ।

उदाहरण के लिए, यदि आप एक विधि लिखते हैं जैसे:

public Double doCalc(final Double value)
{
   final Double maxWeight = 1000.0;
   final Double totalWeight = maxWeight * value;
   return totalWeight;  
}

विधि में चर की घोषणा finalकरने से विधि के बाहर निकलने के बाद विधि में अप्रयुक्त चर से स्मृति को साफ करने में कचरा संग्रह में मदद मिलेगी।

क्या ये सच है?


देखते हैं दो चीज़ें यहाँ वास्तव में,। 1) जब आप एक विधि स्थानीय क्षेत्र और एक उदाहरण के लिए लिखते हैं । जब आप एक उदाहरण के लिए लिखते हैं तो एक लाभ हो सकता है।
यूजीन

जवाबों:


86

यहाँ थोड़ा अलग उदाहरण है, अंतिम संदर्भ प्रकार के स्थानीय चर की बजाय अंतिम संदर्भ-प्रकार वाले क्षेत्र:

public class MyClass {

   public final MyOtherObject obj;

}

हर बार जब आप MyClass का एक उदाहरण बनाते हैं, तो आप एक MyOtherObject उदाहरण के लिए एक आउटगोइंग संदर्भ बना रहे होंगे, और जीसी को लाइव ऑब्जेक्ट देखने के लिए उस लिंक का पालन करना होगा।

जेवीएम एक मार्क-स्वीप जीसी एल्गोरिथ्म का उपयोग करता है, जिसे जीसी "रूट" स्थानों (वर्तमान कॉल स्टैक में सभी ऑब्जेक्ट्स की तरह) में सभी लाइव रिफ़ॉल्ल्स की जांच करनी होती है। प्रत्येक जीवित वस्तु को जीवित होने के रूप में "चिह्नित" किया जाता है, और किसी जीवित वस्तु द्वारा संदर्भित किसी भी वस्तु को जीवित होने के रूप में भी चिह्नित किया जाता है।

मार्क चरण के पूरा होने के बाद, जीसी ढेर के माध्यम से स्वीप करता है, सभी अचिह्नित वस्तुओं के लिए मेमोरी को मुक्त करता है (और शेष जीवित वस्तुओं के लिए मेमोरी को कॉम्पैक्ट करता है)।

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

इसलिए, मेरे सिर के ऊपर से, मैं कहने जा रहा हूं "नहीं, 'अंतिम' मोडिफ़र जीसी को अपने कार्यभार को कम करने में मदद नहीं करता है"।

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

या, बेहतर अभी तक, प्रत्येक घोषणा क्षेत्र के आकार को कम से कम करें। उदाहरण के लिए, यदि आप 1000-लाइन विधि की शुरुआत में एक वस्तु की घोषणा करते हैं, और यदि वस्तु उस विधि के दायरे (अंतिम समापन घुंघराले ब्रेस) के करीब रहने तक जीवित रहती है, तो वह वस्तु ज्यादा समय तक जीवित रह सकती है ज़रूरी।

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


सोच के लिए भोजन। मैंने हमेशा सोचा था कि इनलाइन कोड तेज़ था, लेकिन अगर jvm मेमोरी कम चलाती है तो यह धीमी हो जाएगी।
हम्म्म्म

1
मैं यहां केवल अनुमान लगा रहा हूं ... लेकिन मुझे लगता है कि जेआईटी कंपाइलर अंतिम प्रदर्शन मूल्यों (न कि वस्तुओं) को इनलाइन कर सकता है, मामूली प्रदर्शन बढ़ जाता है। दूसरी ओर कोड इनलाइनिंग, महत्वपूर्ण अनुकूलन का उत्पादन करने में सक्षम है, लेकिन अंतिम चर के साथ इसका कोई लेना-देना नहीं है।
बेंजिस्मिथ

2
यह संभव नहीं है कि पहले से ही बनाए गए अंतिम ऑब्जेक्ट के लिए नल को असाइन किया जाए, फिर शायद मदद के बजाय अंतिम , चीजों को कठिन बना सकता है
हर्नान ईचे

1
एक बड़ी विधि में गुंजाइश को सीमित करने के लिए {} का उपयोग किया जा सकता है, बल्कि इसे कई निजी तरीकों से तोड़ने के बजाय जो अन्य वर्ग विधियों के लिए प्रासंगिक नहीं हो सकता है।
mmm

मैमोरी कचरा संग्रह को बढ़ाने और रिफ़रेंशियल संबंधों को कम करने के लिए जब आप संभव हो तो खेतों के बजाय स्थानीय चर का उपयोग कर सकते हैं।
शिव

37

स्थानीय चर घोषित करने से finalकचरा संग्रहण प्रभावित नहीं होगा, इसका मतलब है कि आप चर को संशोधित नहीं कर सकते। ऊपर दिए गए आपके उदाहरण को संकलित नहीं करना चाहिए क्योंकि आप उस चर को संशोधित कर रहे हैं totalWeightजिसे चिह्नित किया गया है final। दूसरी ओर, एक आदिम ( doubleइसके बजाय Double) घोषित करने से finalउस चर को कॉलिंग कोड में इनबिल्ट किया जा सकेगा, जिससे कुछ मेमोरी और प्रदर्शन में सुधार हो सकता है। इसका उपयोग तब किया जाता है जब आपके पास public static final Stringsएक कक्षा में कई नंबर होते हैं ।

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


26

नहीं, यह सशक्त नहीं है।

याद रखें कि finalइसका मतलब निरंतर नहीं है, इसका मतलब है कि आप संदर्भ को बदल नहीं सकते हैं।

final MyObject o = new MyObject();
o.setValue("foo"); // Works just fine
o = new MyObject(); // Doesn't work.

ज्ञान के आसपास कुछ छोटे अनुकूलन हो सकते हैं जो जेवीएम को संदर्भ को संशोधित करने के लिए कभी नहीं होगा (जैसे कि यह देखने के लिए कि यह बदल गया है कि नहीं की जाँच करें) लेकिन यह इतना छोटा होगा जितना कि चिंता न करें।

Final डेवलपर के लिए उपयोगी मेटा-डेटा के रूप में सोचा जाना चाहिए और संकलक अनुकूलन के रूप में नहीं।


17

स्पष्ट करने के लिए कुछ बिंदु:

  • संदर्भ को बाहर निकालने से GC को मदद नहीं मिलनी चाहिए। यदि ऐसा किया जाता है, तो यह इंगित करता है कि आपके चर खत्म हो गए हैं। एक अपवाद वस्तु नेपोटिज्म का मामला है।

  • जावा में अभी तक कोई ऑन-स्टैक आवंटन नहीं है।

  • वैरिएबल फाइनल घोषित करने का मतलब है कि आप (सामान्य परिस्थितियों में) उस वैरिएबल को नया मान नहीं दे सकते। चूँकि फाइनल स्कोप के बारे में कुछ नहीं कहता है, यह GC पर इसके प्रभाव के बारे में कुछ नहीं कहता है।


जावा में स्टैक आवंटन (आदिम और वस्तुओं के संदर्भ) में है: stackoverflow.com/a/8061692/32453 जावा को एक अनाम वर्ग / लैम्ब्डा के समान बंद होने में वस्तुओं की आवश्यकता होती है, साथ ही साथ अंतिम होने के लिए, लेकिन मुड़ता है बाहर है कि बस "स्मृति आवश्यक / फ्रेम" को कम करने के लिए / भ्रम को कम करने के लिए असंबंधित किया जा रहा है इसके एकत्र करने के लिए ...
rogerdpack

11

ठीक है, मैं इस मामले में "अंतिम" संशोधक के उपयोग या जीसी पर इसके प्रभाव के बारे में नहीं जानता।

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

मैं केवल मौजूदा एपीआई द्वारा आवश्यक होने पर, या जब मुझे अशक्त आदिम की आवश्यकता होती है तो मैं बॉक्सिंग प्राइमेटिव का उपयोग करता हूं।


1
तुम सही हो। मुझे केवल अपने प्रश्न को समझाने के लिए एक त्वरित उदाहरण की आवश्यकता थी।
गोरान मार्टिनिक

5

प्रारंभिक कार्य (कंपाइलर द्वारा लागू) के बाद अंतिम चर नहीं बदले जा सकते हैं।

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

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

final boolean debug = false;

......

if (debug) {
  System.out.println("DEBUG INFO!");
}

प्रिंटलाइन को बाइट कोड में शामिल नहीं किया जाएगा।


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

ठीक है, मुझे सिर्फ पांडित्य हो रहा था; और कुछ नहीं; यह भी एक उत्तर दिया
यूजीन

4

जनरेशनल कचरा लेनेवालों के साथ एक बहुत प्रसिद्ध कोने का मामला नहीं है। (संक्षिप्त विवरण के लिए बेंजिस्मिथ द्वारा उत्तर पढ़ें लिए पढ़ें गहन अंतर्दृष्टि के लिए लेख को अंत में पढ़ें)।

जनरेशनल जीसी में विचार यह है कि ज्यादातर समय केवल युवा पीढ़ियों पर विचार करने की आवश्यकता है। मूल स्थान को संदर्भ के लिए स्कैन किया जाता है, और फिर युवा पीढ़ी की वस्तुओं को स्कैन किया जाता है। इस दौरान अधिक बार झाडू लगाने से पुरानी पीढ़ी में किसी वस्तु की जाँच नहीं होती है।

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

एक पुरानी वस्तु को किसी छोटे से संदर्भित नहीं किया जा सकता है, क्योंकि पुरानी वस्तु को मामूली संग्रहों में नहीं जांचा जाता है, यदि वस्तु का एकमात्र संदर्भ पुरानी वस्तु में रखा जाता है, तो यह चिह्नित नहीं होगा, और गलत होगा स्वीप स्टेज के दौरान निपटाया गया।

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

आलेख:

कचरा संग्रहण पर आईबीएम: हॉटस्पॉट जेवीएम और प्रदर्शन में इतिहास । यह अब पूरी तरह से मान्य नहीं हो सकता है, क्योंकि यह 2003/04 में वापस आता है, लेकिन वे जीसी में अंतर्दृष्टि पढ़ने में कुछ आसान देते हैं।

ट्यूनिंग कचरा संग्रह पर सूर्य


3

जीसी अगम्य refs पर कार्य करता है। इसका "अंतिम" से कोई लेना-देना नहीं है, जो केवल एक बार के असाइनमेंट का दावा है। क्या यह संभव है कि कुछ वीएम की जीसी "फाइनल" का उपयोग कर सकती है? मैं नहीं देखता कि कैसे या क्यों।


3

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


2

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

आपके सवाल का जवाब एक जोरदार नहीं है।


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

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

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

@WernerVanBelle मैं वास्तव में साज़िश कर रहा हूँ, क्या आप एक उदाहरण दे सकते हैं? मैं यह नहीं देखता कि गैर-अंतिम चर के लिए एक अंतिम असाइनमेंट कैसे हो सकता है जिसके बारे में कंपाइलर को पता नहीं है। कंपाइलर जानता है कि यदि आपके पास एक असिंचित चर है, तो यह आपको इसका उपयोग नहीं करने देगा। यदि आप लूप के अंदर एक अंतिम चर को असाइन करने का प्रयास करते हैं, तो संकलक आपको नहीं जाने देगा। ऐसा उदाहरण क्या है जहां एक चर जिसे अंतिम रूप में घोषित किया जा सकता है, लेकिन नहीं है, और संकलक गारंटी नहीं दे सकता है कि यह अंतिम है? मुझे संदेह है कि कोई भी उदाहरण एक चर होगा जिसे पहले स्थान पर अंतिम घोषित नहीं किया जा सकता है।
मैट क्विगले

आपकी टिप्पणी को फिर से पढ़ने के बाद, मैं देखता हूं कि आपका उदाहरण एक सशर्त ब्लॉक के अंदर एक चर है। जब तक सभी स्थिति पथ एक बार चर को प्रारंभ नहीं करते हैं, तब तक वे चर पहले स्थान पर अंतिम नहीं हो सकते। इसलिए, कंपाइलर को इस तरह की घोषणाओं के बारे में पता है - यही कारण है कि यह आपको दो अलग-अलग स्थानों (विचार final int x; if (cond) x=1; else x=2;) में आरंभिक चर को संकलित करने की अनुमति देता है । कंपाइलर, अंतिम कीवर्ड के बिना, इसलिए गारंटी दे सकता है कि एक चर अंतिम है या नहीं।
मैट क्विगले

1

सभी विधियों और चर को उपवर्गों में ओवरडाइट द्वारा अधिग्रहित किया जा सकता है। यदि हम उपवर्गों को सुपरक्लास के सदस्यों से अधिक से अधिक बचाना चाहते हैं, तो हम उन्हें कीवर्ड अंतिम का उपयोग करके अंतिम रूप में घोषित कर सकते हैं। उदाहरण के लिए- final int a=10; final void display(){......} एक विधि को अंतिम बनाना यह सुनिश्चित करता है कि सुपरक्लास में परिभाषित कार्यक्षमता को कभी भी नहीं बदला जाएगा। इसी प्रकार अंतिम चर का मान कभी नहीं बदला जा सकता है। अंतिम चर वर्ग चर की तरह व्यवहार करते हैं।


1

उदाहरण के क्षेत्रों के बारे में सख्ती से बोलना , प्रदर्शन में सुधार कर final सकता है यदि कोई विशेष जीसी शोषण करना चाहता है। जब एक समवर्ती GCहोता है (इसका मतलब है कि आपका आवेदन अभी भी चल रहा है, जबकि जीसी चल रहा है ), इसे व्यापक स्पष्टीकरण के लिए देखें , जीसी को लिखने और / या पढ़ने पर कुछ बाधाओं को नियोजित करना पड़ता है। जो लिंक मैंने आपको दिया है, वह बहुत कुछ बताता है, लेकिन इसे वास्तव में छोटा करने के लिए: जब कोई GCसमवर्ती कार्य करता है, सभी ढेर को पढ़ते हैं और लिखते हैं (जबकि जीसी चल रहा है), "इंटरसेप्टेड" हैं और बाद में समय पर लागू होते हैं; ताकि समवर्ती जीसी चरण समाप्त हो सके।

उदाहरण के finalलिए फ़ील्ड, चूंकि उन्हें संशोधित नहीं किया जा सकता (जब तक कि प्रतिबिंब नहीं), इन बाधाओं को छोड़ा जा सकता है। और यह सिर्फ शुद्ध सिद्धांत नहीं है।

Shenandoah GCउन्हें व्यवहार में है (हालांकि लंबे समय तक नहीं ), और आप उदाहरण के लिए, कर सकते हैं:

-XX:+UnlockExperimentalVMOptions  
-XX:+UseShenandoahGC  
-XX:+ShenandoahOptimizeInstanceFinals

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


0

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


0

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


0

जब मैं अंतिम रूप से स्थानीय चर घोषित करना चाहता हूं, तब ही:

  • मैं है उन्हें अंतिम इतना है कि वे कुछ अनाम वर्ग के साथ साझा किया जा सकता बनाने के लिए (उदाहरण के लिए: डेमॉन धागा बनाने और इसे विधि enclosing से कुछ मूल्य तक पहुंचने देने के)

  • मैं उन्हें अंतिम रूप देना चाहता हूं (उदाहरण के लिए: कुछ मूल्य जो गलती से ओवरराइड नहीं होना चाहिए / नहीं होना चाहिए)

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

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