स्थिर चर को कब आरंभ किया जाता है?


87

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

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


2
कृपया अपने प्रश्न को संपादित करने के लिए अपना प्रश्न संपादित कर सकते हैं।
ओलिवर चार्ल्सवर्थ

1
क्या आपने जावा भाषा विनिर्देशन पढ़ा है? यह एक बहुत पठनीय दस्तावेज़ है, जानबूझकर ऐसा है। यदि आपने वह पढ़ा है, तो आप समझ सकते हैं कि क्या चल रहा है। यदि नहीं, तो आप न्यूनतम पर एक अधिक विशिष्ट प्रश्न पूछ सकते हैं ...
मार्टन बॉडेस

मुझे लगता है कि इस क्यू एंड ए के एक dup है stackoverflow.com/questions/3499214
स्टीफन सी

जवाबों:


72

जावा स्थैतिक चर विधियों से देखें :

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

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

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

आंतरिक कक्षाओं के मामले में , उनके पास स्थिर क्षेत्र नहीं हो सकते हैं

एक आंतरिक वर्ग एक नेस्टेड वर्ग है जो स्पष्ट रूप से या स्पष्ट रूप से घोषित नहीं है static

...

आंतरिक वर्ग स्थैतिक आरंभीकरणकर्ता ()8.7) या सदस्य इंटरफेस की घोषणा नहीं कर सकते ...

हो सकता है कि भीतर के वर्ग स्थिर सदस्यों की घोषणा न करें, जब तक कि वे निरंतर चर न हों ...

JLS 8.1.3 आंतरिक कक्षाएं और संलग्नक उदाहरण देखें

finalजावा में फ़ील्ड को उनके घोषणा स्थान से अलग किया जा सकता है, हालांकि यह static finalफ़ील्ड पर लागू नहीं हो सकता है । नीचे दिए गए उदाहरण देखें।

final class Demo
{
    private final int x;
    private static final int z;  //must be initialized here.

    static 
    {
        z = 10;  //It can be initialized here.
    }

    public Demo(int x)
    {
        this.x=x;  //This is possible.
        //z=15; compiler-error - can not assign a value to a final variable z
    }
}

ऐसा इसलिए है क्योंकि प्रकार के प्रत्येक उदाहरण के साथ संबंधित प्रकारों की सिर्फ एक प्रति है static, उदाहरण के चर के साथ प्रकार के प्रत्येक उदाहरण के साथ जुड़े हुए हैं और अगर हम निर्माणकर्ता के भीतर zप्रकार static finalको आरंभीकृत करने का प्रयास करते हैं, तो यह static finalप्रकार के क्षेत्र को फिर से संगठित करने का प्रयास करेगा। zक्योंकि कंस्ट्रक्टर को क्लास के प्रत्येक इंस्टेंटेशन पर चलाया जाता है जो कि स्थिर finalफ़ील्ड में नहीं होना चाहिए ।


5
In case of static inner classes, they can not have static fieldsएक टाइपो की तरह लगता है। भीतरी वर्ग गैर-स्थैतिक हैं।
डैनियल लुबरोव

आपको हालांकि इसके बजाय का उपयोग करना चाहिए
सूरज जैन

जब आप एक जेवीएम को आग लगाते हैं और पहली बार एक कक्षा को लोड करते हैं (यह क्लास लोडर द्वारा किया जाता है जब कक्षा को किसी भी तरह से संदर्भित किया जाता है) किसी भी स्थिर ब्लॉक या फ़ील्ड को जेवीएम में लोड किया जाता है और सुलभ हो जाता है।
nhoxbypass

1
दुर्भाग्यवश इस उत्तर में कुछ तथ्यात्मक रूप से गलतियां हैं, जब स्टेटिक्स को इनिशियलाइज़ किया जाता है। कृपया stackoverflow.com/a/3499322/139985 देखें ।
स्टीफन सी

15

देख:

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

मुझे यकीन नहीं है कि बिंदु 3 के बारे में आपका विशिष्ट प्रश्न (यह मानते हुए कि आपके पास नेस्टेड है?)। विस्तृत अनुक्रम बताता है कि यह एक पुनरावर्ती आरंभीकरण अनुरोध होगा इसलिए यह आरंभीकरण जारी रखेगा।


11

जब क्लास लोडर द्वारा कक्षा को लोड किया जाता है तो स्टेटिक फ़ील्ड को प्रारंभ किया जाता है। इस समय डिफ़ॉल्ट मान असाइन किए गए हैं। यह स्रोत कोड में दिखाई देने के क्रम में किया जाता है।


10

आरंभीकरण का क्रम है:

  1. स्थैतिक आरंभीकरण ब्लॉक
  2. उदाहरण प्रारंभिककरण ब्लॉक
  3. कंस्ट्रक्टर्स

प्रक्रिया का विवरण जेवीएम विनिर्देश दस्तावेज़ में समझाया गया है ।


6

स्थिर चर

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

4

अन्य प्रश्न से कोड के साथ शुरू:

class MyClass {
  private static MyClass myClass = new MyClass();
  private static final Object obj = new Object();
  public MyClass() {
    System.out.println(obj); // will print null once
  }
}

इस वर्ग के लिए एक संदर्भ प्रारंभ होगा। सबसे पहले, वर्ग को प्रारंभिक के रूप में चिह्नित किया जाएगा। तब पहले स्थिर क्षेत्र को MyClass () के एक नए उदाहरण के साथ आरंभ किया जाएगा। ध्यान दें कि myClass को तुरंत रिक्त MyClass उदाहरण के लिए दिया जाता है । अंतरिक्ष है, लेकिन सभी मान शून्य हैं। कंस्ट्रक्टर को अब निष्पादित और प्रिंट objकिया जाता है, जो शून्य है।

अब कक्षा को शुरू करने के लिए वापस: objएक नई वास्तविक वस्तु का संदर्भ दिया जाता है, और हम काम कर रहे हैं।

यदि यह एक बयान द्वारा सेट किया गया था जैसे: MyClass mc = new MyClass();एक नया MyClass उदाहरण के लिए स्थान फिर से आवंटित किया गया है (और संदर्भ में रखा गया है mc)। कंस्ट्रक्टर को फिर से निष्पादित किया जाता है और फिर से प्रिंट करता है obj, जो अब शून्य नहीं है।

यहां वास्तविक चाल यह है कि जब आप उपयोग करते हैं new, WhatEverItIs weii = new WhatEverItIs( p1, p2 ); weiiतो तुरंत ही थोड़ी अशक्त स्मृति का संदर्भ दिया जाता है। तब जेवीएम मूल्यों को शुरू करने और निर्माणकर्ता को चलाने के लिए आगे बढ़ेगा। लेकिन अगर आप किसी तरह weii से पहले ऐसा करते हैं, तो इसका संदर्भ - दूसरे धागे से या या वर्ग आरंभीकरण से संदर्भित करके, उदाहरण के लिए - आप अशक्त मूल्यों से भरे एक वर्ग उदाहरण को देख रहे हैं।


1
एक वर्ग को तब तक चिह्नित नहीं किया जाता है जब तक कि प्रारंभिककरण पूरा नहीं हो जाता है - अन्यथा ऐसा करने से कोई मतलब नहीं होगा। प्रारंभिक के रूप में चिह्नित करना लगभग अंतिम चरण है। JLS 12.4.2 देखें ।
डेव न्यूटन

@DaveNewton: एक बार जब कोई चीज़ कक्षा का संदर्भ लेती है और इसे शुरू करना शुरू कर देती है, तो आगे के सभी संदर्भ कक्षा को प्रारंभिक मान लेंगे। वे इसे आरंभ करने का प्रयास नहीं करेंगे, और वे इसके आरंभ होने की प्रतीक्षा नहीं करेंगे। इसलिए जो प्रोग्राम की शुरुआत से नहीं दिखाई देते हैं वे फ़ील्ड वास्तव में एक समय के लिए शून्य हो सकते हैं। यह समझ में नहीं आ रहा है कि सभी भ्रम का कारण क्या है। मुझे लगता है कि यह कहना सबसे आसान है कि एक असंगठित वर्ग "चिह्नित" है, क्योंकि पहले संदर्भ में इसे प्रारंभिक रूप में लिखा गया है, अन्य सभी संदर्भ इसे अक्षुण्ण मानते हैं और यही कारण है कि ऐसा होता है।
राल्फचैपिन

पिछली टिप्पणी में एक सुधार: जैसा कि डेव न्यूटन के JLS 12.4.2 में वर्णित है, प्रारंभिक होने के दौरान वर्ग लॉक है। अन्य सूत्र वर्ग के आरंभ होने की प्रतीक्षा करेंगे । हालांकि, इस मामले को प्रभावित नहीं करता है, जो सभी एक धागे में होता है।
राल्फचैपिन 23

4

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

  1. आप घोषणा के समय इसे बदल सकते हैं
  2. या आप स्थिर ब्लॉक बनाकर कर सकते हैं जैसे:

    static {
            // whatever code is needed for initialization goes here
        }
    
  3. स्थैतिक ब्लॉकों का एक विकल्प है - आप एक निजी स्थैतिक विधि लिख सकते हैं

    class name {
        public static varType myVar = initializeVar();
    
        private static varType initializeVar() {
            // initialization code goes here
        }
    }
    
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.