जावा में स्थानीय चर क्यों नहीं शुरू किए जाते हैं?


103

क्या कोई कारण था कि जावा के डिजाइनरों को लगा कि स्थानीय चरों को डिफ़ॉल्ट मान नहीं दिया जाना चाहिए? गंभीरता से, यदि उदाहरण चर को एक डिफ़ॉल्ट मान दिया जा सकता है, तो हम स्थानीय चर के लिए ऐसा क्यों नहीं कर सकते हैं?

और यह एक ब्लॉग पोस्ट के लिए इस टिप्पणी में बताई गई समस्याओं की ओर जाता है :

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

अधिक निराश।



1
इस बारे में क्षमा करें ... यह प्रश्न तब पॉपअप नहीं हुआ जब मैं प्रश्न में टाइप कर रहा था .. हालाँकि, मुझे लगता है कि दोनों प्रश्नों में अंतर है ... मैं जानना चाहता हूं कि जावा के डिजाइनरों ने इसे इस तरह से डिजाइन क्यों किया , जबकि आपके द्वारा पूछा गया सवाल यह नहीं पूछता है कि ...
शिवसुब्रमण्यम ए

इस संबंधित C # प्रश्न को भी देखें: stackoverflow.com/questions/1542824/…
Raedwald

बस - क्योंकि यह संकलक के लिए असंगठित स्थानीय चर को ट्रैक करना आसान है। यदि यह अन्य चर के साथ एक ही कर सकता है, तो यह होगा। संकलक सिर्फ आपकी मदद करने की कोशिश कर रहा है।
रस्टीक्स

जवाबों:


62

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


23

इस समस्या का वर्णन करने के लिए आप जिस "समस्या" से जुड़ते हैं:

SomeObject so;
try {
  // Do some work here ...
  so = new SomeObject();
  so.DoUsefulThings();
} finally {
  so.CleanUp(); // Compiler error here
}

टिप्पणीकार की शिकायत यह है कि कंपाइलर finallyअनुभाग में लाइन पर बैक्स करता है , यह दावा करता है कि soयह असिंचित हो सकता है। टिप्पणी में कोड लिखने के दूसरे तरीके का उल्लेख है, शायद कुछ इस तरह से:

// Do some work here ...
SomeObject so = new SomeObject();
try {
  so.DoUsefulThings();
} finally {
  so.CleanUp();
}

टिप्पणीकार उस समाधान से नाखुश है क्योंकि तब कंपाइलर कहता है कि कोड "एक कोशिश के भीतर होना चाहिए।" मुझे लगता है कि कोड के कुछ का मतलब है कि एक अपवाद है कि अब और नहीं संभाला है बढ़ा सकते हैं। मुझे यकीन नहीं है। मेरे कोड का कोई भी संस्करण किसी भी अपवाद को नहीं संभालता है, इसलिए पहले संस्करण में अपवाद-संबंधित कुछ भी दूसरे में काम करना चाहिए।

वैसे भी, कोड का यह दूसरा संस्करण इसे लिखने का सही तरीका है। पहले संस्करण में, संकलक का त्रुटि संदेश सही था। soचर अप्रारंभीकृत हो सकता है। विशेष रूप से, यदि SomeObjectनिर्माता विफल soहो जाता है, तो उसे प्रारंभ नहीं किया जाएगा, और इसलिए इसे कॉल करने का प्रयास करने में त्रुटि होगी so.CleanUp। आपके द्वारा संसाधन को हासिल करने के बाद हमेशा tryअनुभाग में प्रवेश करें जो कि अनुभाग को अंतिम रूप देता है।finally

try- finallyके बाद ब्लॉक soप्रारंभ होती है केवल रक्षा के लिए SomeObjectउदाहरण के लिए, कोई बात नहीं क्या किसी और होता है यकीन है कि यह साफ हो जाता है बनाने के लिए। यदि अन्य चीजें हैं जिन्हें चलाने की आवश्यकता है, लेकिन वे संबंधित नहीं हैं कि क्या SomeObjectउदाहरण के लिए संपत्ति आवंटित की गई थी, तो उन्हें दूसरे में जाना चाहिए try- finallyब्लॉक, शायद वह जो मैंने दिखाया है वह लपेटता है।

चर का उपयोग करने से पहले मैन्युअल रूप से असाइन करने की आवश्यकता होती है, जिससे वास्तविक समस्याएं नहीं होती हैं। यह केवल मामूली परेशानियों की ओर जाता है, लेकिन आपका कोड इसके लिए बेहतर होगा। आपके पास अधिक सीमित दायरे वाले चर होंगे, और try- वे finallyब्लॉक जो बहुत अधिक सुरक्षा की कोशिश नहीं करते हैं।

यदि स्थानीय चर में डिफ़ॉल्ट मान होते, तो soपहले उदाहरण में होता null। यह वास्तव में कुछ भी हल नहीं होता। में एक संकलन समय त्रुटि हो रही करने के बजाय finallyब्लॉक, आप एक होगा NullPointerExceptionवहाँ गुप्त है कि हो सकता है छिपाने जो कुछ भी अन्य अपवाद कोड के "यहाँ कुछ काम करें" खंड में हो सकता है। (या finallyअनुभागों में अपवाद स्वचालित रूप से पिछले अपवाद को श्रृंखलाबद्ध करते हैं; मुझे याद नहीं है। फिर भी, आपके पास वास्तविक अपवाद के रूप में एक अतिरिक्त अपवाद होगा।)


2
अंत में ब्लॉक में क्यों नहीं (यदि! = null) ...
izb

यह अभी भी संकलक चेतावनी / त्रुटि का कारण होगा - मुझे नहीं लगता कि संकलक समझता है कि अगर जाँच (लेकिन im सिर्फ इस बंद स्मृति कर रहा है, परीक्षण नहीं)।
Chii

6
मैं बस SomeObject लगाऊंगा = कोशिश करने से पहले अशक्त और अंत में खंड करने के लिए अशक्त जाँच डाल दिया। इस तरह कोई संकलक चेतावनी नहीं होगी।
जूहा सिरजला

क्यों उलझी बातें? कोशिश अंत में इस तरह से लिखें, और आप जानते हैं कि चर का एक वैध मूल्य है। कोई शून्य-जाँच की आवश्यकता नहीं है।
रॉब कैनेडी

1
रोब, आपका उदाहरण "नया SomeObject ()" सरल है और कोई अपवाद वहां उत्पन्न नहीं किया जाना चाहिए, लेकिन यदि कॉल अपवाद उत्पन्न कर सकता है, तो बेहतर होगा कि इसे कोशिश-ब्लॉक के अंदर होने दें ताकि इसे संभाला जा सके।
सेरेल बोथा

12

इसके अलावा, नीचे दिए गए उदाहरण में, कोई अपवाद SomeObject निर्माण के अंदर फेंका गया हो सकता है, जिस स्थिति में 'so' वैरिएबल अशक्त होगा और CleanUp पर कॉल NullPointerException को फेंक देगा

SomeObject so;
try {
  // Do some work here ...
  so = new SomeObject();
  so.DoUsefulThings();
} finally {
  so.CleanUp(); // Compiler error here
}

मैं यह करने के लिए क्या कर रहा हूँ:

SomeObject so = null;
try {
  // Do some work here ...
  so = new SomeObject();
  so.DoUsefulThings();
} finally {
  if (so != null) {
     so.CleanUp(); // safe
  }
}

12
अन्यथा आपके द्वारा क्या किया जाएगा?
इलेक्ट्रिक भिक्षु

2
हाँ, बदसूरत। हाँ, यह भी मैं क्या कर रहा है।
SMBiggs

@ElectricMonk आपको कौन-सा रूप बेहतर लगता है, जिसे आपने दिखाया या जो यहां गेटकंट्स
एटम

11

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

दूसरी ओर, गैर-अंतिम सदस्य चर बाद में बदले जा सकते हैं। इसलिए कंपाइलर उन्हें बिना इजाजत के ठीक नहीं रहने देते, क्योंकि बाद में इन्हें बदला जा सकता है। स्थानीय चरों के संबंध में, स्थानीय चरों का दायरा बहुत कम होता है। कंपाइलर जानता है कि इसका उपयोग कब किया जा रहा है। इसलिए, प्रोग्रामर को वैरिएबल को शुरू करने के लिए मजबूर करना समझ में आता है।


9

आपके प्रश्न का वास्तविक उत्तर इसलिए है क्योंकि स्टैक पॉइंटर में एक संख्या को जोड़कर विधि चर को तत्काल दिया जाता है। उन्हें शून्य करना एक अतिरिक्त कदम होगा। वर्ग चर के लिए उन्हें ढेर पर प्रारंभिक स्मृति में रखा जाता है।

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

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

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

उस के शीर्ष पर, स्पष्ट रूप से "int size = 0" के बजाय "int size" कहना बेहतर नहीं है और अगले प्रोग्रामर को यह पता लगाने के लिए कि आप इसे शून्य होने का इरादा रखते हैं?

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


1
हां, और अन्य ऐसे भी हैं जहां कोड कम होने के कारण इसे कम या ज्यादा करना पड़ता है, क्योंकि मुझे इसको प्रतिबिंबित करने के लिए उत्तर "अपडेट" नहीं करना चाहिए।
बिल के

4

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


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

2
हां, लेकिन कोई यह तर्क दे सकता है कि इससे प्रोग्रामर को पता चल सकता है कि क्या उसने गलती से वैरिएबल को छोड़ दिया है।
मेहरदाद आफश्री

1
कंपाइलर ऐसा भी कर सकता है। :) व्यक्तिगत रूप से, मैं पसंद करूंगा कि संकलक एक त्रुटि के रूप में एक असंबद्ध चर का इलाज करता है। इसका मतलब है कि मैंने कहीं गलती की होगी।
ग्रेग हेवगिल

मैं एक जावा लड़का नहीं हूं, लेकिन मुझे इसे संभालने का C # तरीका पसंद है। इस मामले में अंतर यह है कि संकलक को एक चेतावनी जारी करनी थी, जिससे आपको अपने सही कार्यक्रम के लिए कुछ सौ चेतावनी मिल सकती है;)
मेहरदाद आफश्री

क्या यह सदस्य चर के लिए भी चेतावनी देता है?
अदिल अंसारी

4

(प्रश्न के इतने लंबे समय बाद एक नया उत्तर पोस्ट करना अजीब लग सकता है, लेकिन एक डुप्लिकेट सामने आया।)

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

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

मैं स्थानीय चर को डिफ़ॉल्ट करने के पीछे नहीं जा सका , हालाँकि। हां, हमें अपने तर्क को दोबारा जांचने के लिए संकलक पर निर्भर नहीं होना चाहिए, और कोई ऐसा नहीं करता है, लेकिन यह तब भी आसान है जब कंपाइलर एक को पकड़ता है। :-)


"उस ने कहा, मैं पूरी तरह से पीछे पड़ सकता है कि उदाहरण चर हमेशा स्पष्ट रूप से आरंभिक थे ..." जो, FWIW, वह दिशा है जो उन्होंने टाइपस्क्रिप्ट में ली है।
टीजे क्राउडर

3

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

ऐसे मामलों में जहां आपको एक वैरिएबल की आवश्यकता होती है, आप इसे हमेशा स्वयं कर सकते हैं, इसलिए यह कोई समस्या नहीं है।


3

स्थानीय चरों के पीछे का विचार यह है कि वे केवल उस सीमित दायरे के अंदर मौजूद हैं जिसके लिए उनकी आवश्यकता है। जैसे, मूल्य के रूप में अनिश्चितता के लिए बहुत कम कारण होना चाहिए, या कम से कम, वह मूल्य कहां से आ रहा है। मैं स्थानीय चर के लिए डिफ़ॉल्ट मान होने से उत्पन्न होने वाली कई त्रुटियों की कल्पना कर सकता हूं।

उदाहरण के लिए, निम्नलिखित सरल कोड पर विचार करें ... ( NB हमें प्रदर्शन उद्देश्यों के लिए मान लें कि स्थानीय चर एक डिफ़ॉल्ट मान निर्दिष्ट किए गए हैं, जैसा कि निर्दिष्ट किया गया है, यदि स्पष्ट रूप से आरंभिक नहीं है )

System.out.println("Enter grade");
int grade = new Scanner(System.in).nextInt(); //I won't bother with exception handling here, to cut down on lines.
char letterGrade; //let us assume the default value for a char is '\0'
if (grade >= 90)
    letterGrade = 'A';
else if (grade >= 80)
    letterGrade = 'B';
else if (grade >= 70)
    letterGrade = 'C';
else if (grade >= 60)
    letterGrade = 'D';
else
    letterGrade = 'F';
System.out.println("Your grade is " + letterGrade);

जब सब कहा और किया जाता है, तो मान लेते हैं कि संकलक ने पत्र \ _ को डिफ़ॉल्ट मान निर्दिष्ट किया है , यह कोड ठीक से काम करेगा। हालाँकि, अगर हम दूसरे कथन को भूल गए तो क्या होगा?

हमारे कोड का परीक्षण रन निम्नलिखित में हो सकता है

Enter grade
43
Your grade is

यह परिणाम, जबकि उम्मीद की जा रही थी, निश्चित रूप से कोडर का इरादा नहीं था। वास्तव में, संभवतः अधिकांश मामलों में (या कम से कम, एक महत्वपूर्ण संख्या), डिफ़ॉल्ट मान वांछित मूल्य नहीं होगा , इसलिए अधिकांश मामलों में डिफ़ॉल्ट मान में त्रुटि होगी। कोडर को मजबूर करने के लिए इसका उपयोग करने से पहले एक स्थानीय चर के लिए एक प्रारंभिक मान निर्दिष्ट करने के लिए अधिक समझ में आता है, क्योंकि डीबगिंग दु: ख = 1को for(int i = 1; i < 10; i++)दूर करने की सुविधा में भूल जाने के कारण अंदर शामिल करने की सुविधा नहीं = 0है for(int i; i < 10; i++)

यह सच है कि ट्राइ-कैच-अंत में ब्लॉक थोड़ा गड़बड़ हो सकता है (लेकिन यह वास्तव में एक कैच -22 नहीं है जैसा कि उद्धरण से पता चलता है), जब उदाहरण के लिए कोई ऑब्जेक्ट अपने कंस्ट्रक्टर में एक चेक किए गए अपवाद को फेंकता है, फिर भी एक के लिए कारण या कोई अन्य, अंत में ब्लॉक के अंत में इस ऑब्जेक्ट के लिए कुछ किया जाना चाहिए। इसका एक आदर्श उदाहरण संसाधनों के साथ काम करना है, जिसे बंद किया जाना चाहिए।

अतीत में इसे संभालने का एक तरीका ऐसा हो सकता है ...

Scanner s = null; //declared and initialized to null outside the block. This gives us the needed scope, and an initial value.
try {
    s = new Scanner(new FileInputStream(new File("filename.txt")));
    int someInt = s.nextInt();
} catch (InputMismatchException e) {
    System.out.println("Some error message");
} catch (IOException e) {
    System.out.println("different error message"); 
} finally {
    if (s != null) //in case exception during initialization prevents assignment of new non-null value to s.
        s.close();
}

हालाँकि, जावा 7 के रूप में, यह अंततः ब्लॉक-टू-रिसोर्स का उपयोग करके आवश्यक नहीं है, जैसे कि।

try (Scanner s = new Scanner(new FileInputStream(new File("filename.txt")))) {
...
...
} catch(IOException e) {
    System.out.println("different error message");
}

उस ने कहा, (जैसा कि नाम से पता चलता है) यह केवल संसाधनों के साथ काम करता है।

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

यह सच है कि फ़ील्ड्स को एक डिफ़ॉल्ट मान से आरंभ किया जाता है, लेकिन यह थोड़ा अलग है। जब आप कहते हैं, उदाहरण के लिए, int[] arr = new int[10];जैसे ही आपने इस सरणी को प्रारंभ किया है, ऑब्जेक्ट किसी दिए गए स्थान पर स्मृति में मौजूद है। आइए एक पल के लिए मान लें कि कोई डिफ़ॉल्ट मान नहीं है, लेकिन इसके बजाय प्रारंभिक मूल्य जो भी 1s और 0s की श्रृंखला है, उस समय उस मेमोरी लोकेशन में होता है। इससे कई मामलों में गैर-नियतात्मक व्यवहार हो सकता है।

मान लीजिए हमारे पास ...

int[] arr = new int[10];
if(arr[0] == 0)
    System.out.println("Same.");
else
    System.out.println("Not same.");

यह पूरी तरह से संभव होगा कि Same.एक रन Not same.में प्रदर्शित किया जा सकता है और दूसरे में प्रदर्शित किया जा सकता है। जब आप संदर्भ चर बोलना शुरू करते हैं तो समस्या और भी अधिक गंभीर हो सकती है।

String[] s = new String[5];

परिभाषा के अनुसार, एस के प्रत्येक तत्व को एक स्ट्रिंग (या अशक्त) को इंगित करना चाहिए। हालाँकि, यदि प्रारंभिक मान 0s और 1s की जो भी श्रंखला होती है वह इस मेमोरी लोकेशन पर होती है, यही नहीं इसकी कोई गारंटी नहीं है कि आपको हर बार समान परिणाम मिलेंगे, लेकिन इस बात की भी कोई गारंटी नहीं है कि ऑब्जेक्ट s [0] (यह सार्थक कुछ भी इंगित करता है) यहां तक कि एक स्ट्रिंग है (शायद यह एक खरगोश है : पी )! प्रकार के लिए चिंता की यह कमी जावा जावा को बनाने वाली हर चीज के चेहरे पर उड़ जाएगी। इसलिए जबकि स्थानीय चरों के लिए डिफ़ॉल्ट मानों को सर्वोत्तम रूप में वैकल्पिक रूप में देखा जा सकता है, उदाहरण के चर के लिए डिफ़ॉल्ट मान एक आवश्यकता के करीब है ।


1

अगर मैं गलत नहीं हूँ, एक और कारण हो सकता है

सदस्य चर का डिफ़ॉल्ट मान देना वर्ग लोडिंग का हिस्सा है

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


0

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


0

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


2
गलत बाहर फ्लैट ... सभी जावा गैर-प्राइमेटीज का निर्माण कब और कैसे किया जाता है, इसकी परवाह किए बिना ढेर में संग्रहित किया जाता है
gshauger

जावा 7 से पहले, उदाहरण चर ढेर पर संग्रहीत किए जाते हैं और स्टैक पर स्थानीय चर पाए जाते हैं। हालाँकि, कोई भी ऑब्जेक्ट जो स्थानीय चर संदर्भों को ढेर में मिलेगा। जावा 7 के अनुसार, "जावा हॉटस्पॉट सर्वर कंपाइलर" "एस्केप एनालिसिस" कर सकता है और ढेर के बजाय स्टैक पर कुछ ऑब्जेक्ट आवंटित करने का निर्णय ले सकता है।
मैमिली 16

0

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


-1

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


-2

मैं निम्नलिखित 2 कारणों के बारे में सोच सकता था

  1. जैसा कि अधिकांश उत्तरों में कहा गया है कि स्थानीय चर को शुरू करने की बाधा डालकर, यह सुनिश्चित किया जाता है कि स्थानीय चर को एक मान दिया जाए जैसा कि प्रोग्रामर चाहता है और यह सुनिश्चित करता है कि अपेक्षित परिणाम गणना किए गए हैं।
  2. इंस्टेंस वेरिएबल को स्थानीय वेरिएबल्स (समान नाम) घोषित करके छिपाया जा सकता है - अपेक्षित व्यवहार सुनिश्चित करने के लिए, स्थानीय वेरिएबल्स को एक मूल्य के लिए मजबूर किया जाता है। (हालांकि पूरी तरह से इस से बचना होगा)

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

सही छिपा हुआ है। यदि कोई उदाहरण के रूप में एक ही नाम के साथ स्थानीय चर बनाने का फैसला करता है, तो इस बाधा के कारण, स्थानीय चर को प्रारंभिक रूप से चयनित मान (उदाहरण चर के मूल्य के अलावा) के साथ आरंभ किया जाएगा
मित्रा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.