2015-06-15 5 views
53

निम्नलिखित संकलन नहीं करता है, एक 'अवैध आगे संदर्भ' संदेश दे रही है:दो प्रोग्रामों में त्रुटियों का संदर्भ देने में आगे क्यों है जबकि तीसरा नहीं है?

class StaticInitialisation { 

    static 
    { 
     System.out.println("Test string is: " + testString); 
    } 

    private static String testString; 

    public static void main(String args[]) { 
     new StaticInitialisation(); 
    } 
} 

हालांकि, निम्नलिखित संकलन करता है:

class InstanceInitialisation1 { 

    { 
     System.out.println("Test string is: " + this.testString); 
    } 

    private String testString; 

    public static void main(String args[]) { 
     new InstanceInitialisation1(); 
    } 
} 

लेकिन निम्नलिखित संकलन नहीं करता है, एक 'अवैध आगे दे रही है संदर्भ 'संदेश:

class InstanceInitialisation2 { 

     private String testString1; 

    { 
     testString1 = testString2; 
    } 

    private String testString2; 

    public static void main(String args[]) { 
     new InstanceInitialisation2(); 
    } 
} 

क्यों StaticInitialisation और InstanceInitialisation2 संकलन नहीं है, जबकि InstanceInitialisation1 हिरण रों?

+1

देखने के लिए कि करने के लिए बदल 3 टुकड़ा काम करेगा 'testString1 = this.testString2;' – Eran

+1

इसका पहली बार मैं एक जावा वर्ग में कोड का एक खंड देखना है कि एक ctor का हिस्सा नहीं है, या स्थैतिक सीटीओ, या विधि। यह जानना अच्छा लगेगा कि यह क्या है, यह संकलन कैसे पास करता है और इसे कब –

+12

@sharonbn निष्पादित किया जाता है: वे उदाहरण प्रारंभकर्ता या स्थैतिक प्रारंभकर्ता हैं, क्रमशः जेएलएस की धारा 8.6 और 8.7 में वर्णित हैं। –

उत्तर

57

यह JLS की धारा 8.3.3 द्वारा कवर किया जाता:

वर्ग चर जिसका घोषणाओं से टेक्स्ट रूप में दिखाई के बाद उपयोग कभी कभी ही सीमित है की

उपयोग, भले ही इन वर्ग चर दायरे में हैं (§6.3)।

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

  • उपयोग सी के क्लास वेरिएबल प्रारंभकर्ता या सी के स्थिर प्रारंभकर्ता में एक साधारण नाम है;

  • उपयोग असाइनमेंट के बाईं ओर नहीं है;

  • सी अंतर्निहित कक्षा या इंटरफ़ेस उपयोग को संलग्न करता है।

उदाहरण चर जिसका घोषणाओं से टेक्स्ट रूप में दिखाई के बाद उपयोग कभी कभी, प्रतिबंधित है हालांकि ये उदाहरण चर दायरे में हैं का प्रयोग करें।

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

  • उपयोग सी का एक उदाहरण चर प्रारंभकर्ता या सी के एक उदाहरण प्रारंभकर्ता में एक साधारण नाम है;

  • उपयोग असाइनमेंट के बाईं ओर नहीं है;

  • सी अंतर्निहित कक्षा या इंटरफ़ेस उपयोग को संलग्न करता है।

अपने दूसरे मामले में, उपयोग एक साधारण नाम नहीं है - आप this स्पष्ट रूप से मिल गया है। इसका मतलब है कि यह उपरोक्त उद्धृत दूसरी सूची में दूसरी बुलेट का पालन नहीं करता है, इसलिए कोई त्रुटि नहीं है।

आप के लिए इसे बदल हैं:

System.out.println("Test string is: " + testString); 

...तो यह संकलित नहीं होगा।

या विपरीत दिशा में, आप करने के लिए स्थिर प्रारंभकर्ता ब्लॉक में कोड बदल सकते हैं:

System.out.println("Test string is: " + StaticInitialisation.testString); 

अजीब है, लेकिन इस तरह से यह जाता है।

+1

मैं आपके ट्वीट के कारण यहां आया था, और आपको मेरा +1 मिला, लेकिन यह [नया नहीं] (http://stackoverflow.com/q/15820302/256431) @ bayou.io लिंक के रूप में है। –

+0

@ मार्कहर्ड: हाँ, यह मेरे लिए केवल नया है :) –

1

यहाँ है कि हम क्या समझना होगा 2 कोड में स्निपेट को आप ब्लॉक तथा इस कीवर्ड का उपयोग कर रही है।

  1. ऑब्जेक्ट बनाया गया है तो ब्लॉक निष्पादित करता है।
  2. इसका मतलब है कि वस्तु ढेर क्षेत्र में बनाई गई है।
  3. उदाहरण के लिए आप इस कीवर्ड का उपयोग कर बाहरी रूप से उपयोग कर रहे हैं।
  4. यहां ऑब्जेक्ट डिफ़ॉल्ट मानों के साथ बनाया गया है जो मान के रूप में वापस आ जाएंगे।
  5. इस कीवर्ड का उपयोग करके आप 2 स्निपेट भी संकलित नहीं कर सकते हैं।
2

आइए इन दो उदाहरणों को देखें, मुझे लगता है कि यह आपको स्पष्ट कर देगा।

public class InstanceAndSataticInit { 

    { 
     System.out.println("Test string is (instance init): " + this.testString); 
    } 

    static{ 
     System.out.println("Test string is (static init): " + InstanceAndSataticInit.testStringStatic); 
    } 

    public static String testStringStatic="test"; 
    public String testString="test"; 

    public static void main(String args[]) { 
     new InstanceAndSataticInit(); 
    } 

} 

आउटपुट:

Test string is (static init): null 
Test string is (instance init): null 

और

public class InstanceAndSataticInitVariableFirst { 

    public static String testStringStatic="test"; 
    public String testString="test"; 

    { 
     System.out.println("Test string is (instance init): " + this.testString); 
    } 

    static{ 
     System.out.println("Test string is (static init): " + InstanceAndSataticInitVariableFirst.testStringStatic); 
    } 



    public static void main(String args[]) { 
     new InstanceAndSataticInitVariableFirst(); 
    } 


} 

उत्पादन:

Test string is (static init): test 
Test string is (instance init): test 

तो आप कह सकते हैं अनुक्रम इस तरह कर रहे हैं।

  1. स्टेटिक चर बनाया जाएगा लेकिन प्रारंभ नहीं किया जाएगा।

  2. स्टेटिक प्रारंभिक क्रम दिए गए क्रम के अनुसार निष्पादित किया जाएगा।

  3. गैर स्टेटिक चर बनाया जाएगा लेकिन प्रारंभ नहीं किया जाएगा।
  4. दिए गए अनुक्रम के अनुसार गैर स्टेटिक प्रारंभिक निष्पादित किया जाएगा।

अनुक्रम से मेरा मतलब कोड में उपस्थिति है।

मैं इस कदम का जवाब लगता है कि आपके दो उदाहरण काम नहीं कर रहा StaticInitialisation और InstanceInitialisation2

लेकिन मामला अपने दूसरा काम कर उदाहरण मेंInstanceInitialisation1this कुंजी शब्द आप वास्तव में करने के लिए संकलक मदद कर रहे हैं का उपयोग करके पाठ पदानुक्रम को नजरअंदाज करें।एक ही बात static के मामले में हो सकता है जब मैं अपनी पहली उदाहरण में InstanceAndSataticInit.testStringStatic फोन InstanceAndSataticInit

2

सरल कारण - यह विश्लेषण और सभी आगे संदर्भ ना करे के लिए बहुत महंगा या असंभव है। जैसे

{ 
    print(getX(); ); // this.x 
    print(that().x); // this.x 
} 

int x; 
int getX(){ return x; } 

This that(){ return this; } 

spec सामान्य प्रोग्रामर गलतियों के संकेतक कुछ साधारण मामलों को मना करने पर निर्भर करता है।

भी Recursive initializer works when I add "this"?

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