2017-01-30 13 views
74

मैंने अभी देखा है कि अजीब कोड के दूसरे प्रश्न में कोड का टुकड़ा। मैंने सोचा कि यह एक StackOverflowError फेंके जाने में परिणाम होगा, लेकिन यह नहीं है ...यह कथन एक स्टैक ओवरफ्लो त्रुटि क्यों नहीं फेंकता है?

public class Node { 
    private Object one; 
    private Object two; 
    public static Node NIL = new Node(Node.NIL, Node.NIL); 

    public Node(Object one, Object two) { 
     this.one = one; 
     this.two = two; 
    } 
} 

मैंने सोचा था कि वह खुद को संदर्भित निर्माण करने के लिए Node.NIL की वजह से विस्फोट के लिए जा रहा था,।

मुझे यह नहीं पता कि यह क्यों नहीं है।

+7

शायद 'स्थिर 'की वजह से मुझे यकीन नहीं है कि – XtremeBaumer

+28

मुझे उम्मीद है कि' एनआईएल' फ़ील्ड का निर्माण किया गया है क्योंकि इसे' नया नोड (शून्य, शून्य) 'घोषित किया गया था, क्योंकि जब निर्माता को बुलाया जाता है , 'Node.NIL' अभी तक कुछ भी सेट नहीं किया गया है। – khelwood

+0

@ शेल्वुड हाँ, उत्तर के आधार पर मैं वही सोच समझ गया। –

उत्तर

100

NIL एक स्थिर चर है। कक्षा शुरू होने पर इसे एक बार शुरू किया जाता है। जब इसे प्रारंभ किया जाता है, तो एक Node उदाहरण बनाया जाता है। Node का निर्माण किसी भी अन्य Node उदाहरणों को सृजन नहीं करता है, इसलिए कॉल की अनंत श्रृंखला नहीं है। Node.NIL को कन्स्ट्रक्टर कॉल में पास करने के समान प्रभाव है null गुजरने के बाद, Node.NIL को तब तक प्रारंभ नहीं किया गया जब निर्माता को बुलाया जाता है। इसलिए public static Node NIL = new Node(Node.NIL, Node.NIL);public static Node NIL = new Node(null, null); जैसा ही है।

यदि दूसरी ओर, NIL एक उदाहरण चर था (और Node कन्स्ट्रक्टर के लिए तर्क के रूप में पारित नहीं किया गया था, क्योंकि संकलक आपको उस मामले में निर्माता को पास करने से रोक देगा), यह होगा प्रत्येक बार Node का एक उदाहरण बनाया गया था, जो एक नया Node उदाहरण बनाएगा, जिसका निर्माण NIL इंस्टेंस वैरिएबल को प्रारंभ करेगा, जिससे कन्स्ट्रक्टर कॉल की अनंत श्रृंखला हो जाएगी जो StackOverflowError में समाप्त हो जाएगी।

+0

धन्यवाद, आपने इसे स्पष्ट बना दिया है, जिस तरह से यह काम करता है वह अभी भी मेरे लिए अजीब है। लेकिन कम से कम मैं समझता हूं कि यह इस तरह क्यों काम करता है। –

+5

यदि 'NIL' एक आवृत्ति चर था, तो यह त्रुटि के साथ संकलित नहीं होगा 'परिभाषित होने से पहले किसी फ़ील्ड को संदर्भित नहीं कर सकता'। –

+0

@FlorianGenser अच्छा बिंदु। मैंने इस हिस्से को यह ध्यान देने से पहले लिखा था कि 'नोड एनआईएल' को कन्स्ट्रक्टर को पास कर दिया गया था। – Eran

27

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

NIL = null; // set implicitly 
NIL = new Node(NIL, NIL); 

लेखन आप एक समारोह या विधि परिभाषित हैं के रूप में

public static Node { 
    public static Node NIL; 

    static { 
     NIL = new Node(null /*Node.NIL*/, null /*Node.NIL*/); 
    } 

    public Node(Object one, Object two) { 
     // Assign values to fields 
    } 
} 

ही है यह अलग नहीं है इस तरह, आप understan करने के लिए एक StackoverflowException

Node NIL(Node a, Node b) { 
    return NIL(NIL(a, b), NIL(a, b)); 
} 
20

कुंजी मिलेगा डी क्यों यह अनंत inititialization का कारण नहीं है कि जब वर्ग Node शुरू किया जा रहा है, तो JVM इसके मूल प्रारंभिकरण के भीतर कक्षा के एक पुनरावर्ती संदर्भ के दौरान पुनः प्रारंभ करने से बचाता है। यह this section of the language spec में विस्तृत है:

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

इसलिए जब स्थिर प्रारंभकर्ता स्थिर उदाहरण NIL पैदा कर रही है, निर्माता कॉल के हिस्से के रूप Node.NIL के संदर्भ में स्थिर प्रारंभकर्ता फिर से निष्पादित नहीं करता है। इसके बजाय यह उस संदर्भ में संदर्भ NIL पर जो भी मूल्य मानता है, उस संदर्भ में null है।

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