tl; डॉ
के लिए खेतों , int b = b + 1अवैध वजह से है bकरने के लिए एक अवैध आगे संदर्भ है b। आप वास्तव में इसे लिखकर ठीक कर सकते हैं int b = this.b + 1, जो शिकायतों के बिना संकलन करता है।
के लिए स्थानीय चर , int d = d + 1अवैध है क्योंकि dउपयोग करने से पहले आरंभ नहीं किया है। यह फ़ील्ड के लिए ऐसा नहीं है, जो हमेशा डिफ़ॉल्ट-आरंभिक होता है।
आप संकलन का प्रयास करके अंतर देख सकते हैं
int x = (x = 1) + x;
क्षेत्र घोषणा के रूप में और स्थानीय परिवर्तनशील घोषणा के रूप में। पूर्व विफल हो जाएगा, लेकिन उत्तरार्द्ध सफल होगा, क्योंकि शब्दार्थ में अंतर है।
परिचय
सबसे पहले, फ़ील्ड और स्थानीय वैरिएबल इनिशियलाइज़र के नियम बहुत अलग हैं। तो यह जवाब दो भागों में नियमों से निपटेगा।
हम इस परीक्षण कार्यक्रम का उपयोग करेंगे:
public class test {
int a = a = 1;
int b = b + 1;
public static void Main(String[] args) {
int c = c = 1;
int d = d + 1;
}
}
की घोषणा bअमान्य है और एक illegal forward referenceत्रुटि के साथ विफल हो जाती है ।
की घोषणा dअमान्य है और एक variable d might not have been initializedत्रुटि के साथ विफल हो जाती है ।
यह तथ्य कि ये त्रुटियां अलग हैं, यह संकेत देना चाहिए कि त्रुटियों के कारण भी भिन्न हैं।
खेत
जावा में फील्ड इनिशियलाइज़र JLS .38.3.2 द्वारा शासित होते हैं , फ़ील्ड्स का प्रारंभ।
गुंजाइश एक क्षेत्र के में परिभाषित किया गया है JLS §6.3 घोषणा की गुंजाइश,।
प्रासंगिक नियम हैं:
mकिसी वर्ग प्रकार C (a8.1.6) द्वारा घोषित या विरासत में दिए गए सदस्य की घोषणा का दायरा C का संपूर्ण निकाय है, जिसमें कोई भी नेस्टेड प्रकार की घोषणाएँ शामिल हैं।
- उदाहरण के चर के लिए प्रारंभिक अभिव्यक्तियाँ वर्ग द्वारा घोषित या विरासत में दिए गए किसी भी स्थिर चर के साधारण नाम का उपयोग कर सकती हैं, यहां तक कि जिसका घोषणा पाठ बाद में होता है।
- ऐसे उदाहरण चर का उपयोग जिनकी घोषणाएँ उपयोग के बाद कभी-कभी प्रतिबंधित होती हैं, भले ही ये उदाहरण चर दायरे में हों। चर उदाहरण के लिए आगे संदर्भ को नियंत्रित करने वाले सटीक नियमों के लिए ning8.3.2.3 देखें।
§8.3.2.3 कहता है:
किसी सदस्य की घोषणा को पाठ से पहले प्रदर्शित करने की आवश्यकता होती है, इसका उपयोग केवल तभी किया जाता है जब सदस्य वर्ग या इंटरफ़ेस C का एक उदाहरण (क्रमशः स्थिर) फ़ील्ड हो और निम्नलिखित सभी स्थितियाँ हों:
- उपयोग C के उदाहरण (क्रमशः स्थिर) चर इनीशियलाइज़र में होता है और C के इंस्टेंस में (क्रमशः स्टैटिक) इनिशियलाइज़र होता है।
- उपयोग एक असाइनमेंट के बाईं ओर नहीं है।
- उपयोग एक साधारण नाम से होता है।
- सी, अंतरतम वर्ग या इंटरफ़ेस का उपयोग है।
आप वास्तव में कुछ मामलों को छोड़कर, घोषित किए जाने से पहले खेतों का उल्लेख कर सकते हैं। इन प्रतिबंधों का उद्देश्य कोड को रोकना है
int j = i;
int i = j;
संकलन से। जावा कल्पना कहती है, "ऊपर दिए गए प्रतिबंध संकलन समय, परिपत्र या अन्यथा विकृत प्रारंभिकताओं को पकड़ने के लिए डिज़ाइन किए गए हैं।"
इन नियमों से वास्तव में क्या उबाल आता है?
संक्षेप में, नियम मूल रूप से कहते हैं कि आपको उस फ़ील्ड के संदर्भ में अग्रिम में एक फ़ील्ड घोषित करना होगा यदि (ए) संदर्भ एक इनिशियलाइज़र में है, (बी) संदर्भ को सौंपा नहीं जा रहा है, (सी) संदर्भ एक है सरल नाम (कोई क्वालिफायर नहीं this.) और (डी) इसे एक आंतरिक वर्ग के भीतर से एक्सेस नहीं किया जा रहा है। तो, एक आगे का संदर्भ जो सभी चार स्थितियों को संतुष्ट करता है, अवैध है, लेकिन एक आगे का संदर्भ जो कम से कम एक स्थिति में विफल रहता है, ठीक है।
int a = a = 1;संकलित करता है क्योंकि यह उल्लंघन करता है (बी): संदर्भ a को सौंपा जा रहा है, इसलिए यह पूरी तरह से घोषणा के aअग्रिम में संदर्भित करने के लिए कानूनी है a।
int b = this.b + 1संकलित भी करता है क्योंकि यह उल्लंघन करता है (सी): संदर्भ this.bएक साधारण नाम नहीं है (यह योग्य है this.)। यह विषम निर्माण अभी भी पूरी तरह से परिभाषित है, क्योंकि this.bमूल्य शून्य है।
इसलिए, मूल रूप से, शुरुआती के भीतर क्षेत्र संदर्भों पर प्रतिबंध int a = a + 1सफलतापूर्वक संकलित होने से रोकते हैं ।
ध्यान दें कि फ़ील्ड घोषणा संकलन में विफल हो int b = (b = 1) + bजाएगी , क्योंकि फ़ाइनल अभी भी एक अवैध फ़ॉरवर्ड संदर्भ है।b
स्थानीय चर
स्थानीय चर घोषणाएँ JLS §14.4 द्वारा संचालित होती हैं , स्थानीय परिवर्तनीय घोषणा विवरण।
गुंजाइश एक स्थानीय चर के में परिभाषित किया गया है JLS §6.3 , एक घोषणा के स्कोप:
- एक ब्लॉक में स्थानीय चर घोषणा का दायरा ()14.4) शेष खंड है जिसमें घोषणा प्रकट होती है, अपने स्वयं के प्रारंभकर्ता के साथ शुरू होती है और किसी भी अन्य घोषणाकर्ता को स्थानीय चर घोषणा बयान में दाईं ओर शामिल करती है।
ध्यान दें कि इनिशियलाइज़र वैरिएबल के दायरे में हैं। तो क्यों int d = d + 1;संकलन नहीं है ?
इसका कारण निश्चित कार्य पर जावा के नियम ( JLS .16 ) के कारण है। निश्चित रूप से असाइनमेंट मूल रूप से कहता है कि किसी स्थानीय वैरिएबल की हर एक्सेस में उस वैरिएबल का पूर्ववर्ती असाइनमेंट होना चाहिए, और जावा कंपाइलर लूप और शाखाओं की जांच करता है ताकि यह सुनिश्चित किया जा सके कि असाइनमेंट हमेशा किसी भी उपयोग से पहले होता है (यही कारण है कि निश्चित असाइनमेंट में एक संपूर्ण विनिर्देश अनुभाग समर्पित है यह)। मूल नियम है:
- स्थानीय चर या रिक्त अंतिम फ़ील्ड की प्रत्येक पहुंच के लिए
x, xनिश्चित रूप से एक्सेस से पहले असाइन किया जाना चाहिए, या एक संकलन-समय त्रुटि उत्पन्न होती है।
में int d = d + 1;, dस्थानीय चर ठीक करने के लिए उपयोग किया जाता है, लेकिन जब तक पहुँचने dसे पहले असाइन नहीं किया गया dहै, संकलक एक त्रुटि जारी करता है। में int c = c = 1, c = 1पहले होता है, जो असाइन करता है c, और फिर cउस असाइनमेंट (जो 1 है) के परिणाम के लिए आरंभिक है।
ध्यान दें कि निश्चित असाइनमेंट नियमों के कारण, स्थानीय परिवर्तनीय घोषणा सफलतापूर्वक ( फ़ील्ड घोषणा के विपरीत ) संकलन int d = (d = 1) + d; करेगी , क्योंकि निश्चित रूप से अंतिम पहुंच के समय तक सौंपा गया है।int b = (b = 1) + bdd
staticक्लास-स्कोप वैरिएबल में कीवर्ड जोड़ते हैंstatic int x = x + 1;, तो क्या आपको वही त्रुटि मिलेगी? क्योंकि C # में स्टैटिक या नॉन-स्टैटिक होने पर फर्क पड़ता है।