2013-02-25 17 views
5

एक कोड है जो जूनियर जावा डेवलपर्स के लिए एक कार्य के रूप में दिया जाता है। मैं पांच वर्षों के दौरान जावा का उपयोग करें और कोड के इस टुकड़े पूरी तरह से मुझे भ्रमित:जावा: ऑब्जेक्ट का प्रारंभिक अनुक्रम

public class Main { 

    String variable; 

    public static void main(String[] args) { 
     System.out.println("Hello World!"); 
     B b = new B(); 
    } 

    public Main(){ 
     printVariable(); 
    } 

    protected void printVariable(){ 
     variable = "variable is initialized in Main Class"; 
    } 
} 

public class B extends Main { 

    String variable = null; 

    public B(){ 
     System.out.println("variable value = " + variable); 
    } 

    protected void printVariable(){ 
     variable = "variable is initialized in B Class"; 
    } 
} 

उत्पादन होगा:

Hello World! 
variable value = null 

लेकिन अगर हम String variable = null;String variable; को बदलने हम होगा:

Hello World! 
variable value = variable is initialized in B Class 

दूसरा आउटपुट मेरे लिए अधिक स्पष्ट है। तो, जहाँ तक मैं इस तरह जावा में inizialisation के अनुक्रम पता है:

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

इसके अलावा पोस्ट जो एक सुपर क्लास के संदर्भ में this कीवर्ड के व्यवहार का वर्णन करता है - Calling base class overridden function from base class method

ऊपर दिए गए नियमों के आधार पर, मैं इस तरह अनुक्रम के लिए मान लेते हैं:

  1. हम कक्षा B का एक नया उदाहरण बनाने जा रहे हैं;
  2. हम भाग वर्ग Main पर जाते हैं;
  3. शून्य के साथ main.variable आरंभ करें;
  4. फिर हम वर्ग Main के डिफ़ॉल्ट कन्स्ट्रक्टर पर जाते हैं;
  5. कन्स्ट्रक्टर कॉल कक्षा Main में कॉल करता है; (ऐसा क्यों है main.printvariable फोन नहीं करता है हम this कुंजी शब्द यहाँ नहीं है?।)
  6. क्षेत्र b.variable "चर बी क्लास में आरंभ नहीं हो जाता"
  7. अब हम वर्ग B वापस आने;
  8. हमें शून्य मान के साथ क्षेत्र b.variable प्रारंभ करना चाहिए, क्या मैं सही हूँ?
  9. वर्ग B के डिफ़ॉल्ट निर्माता

कृपया मार डाला, किसी को कैसे इस विरासत inizialisation अनुक्रम काम करता है की एक पूरी और पूर्ण विवरण दे सकते हैं।और String variable = null; से String variable; क्यों बदल रहा है एक और आउटपुट की ओर जाता है।

+1

printVariable (किराए पर नहीं है तो क्या होगा सकते हैं) एक बहुत भ्रामक विधि का नाम है - (setVariable की तरह अधिक होना चाहिए) – Jimmt

+1

आप 5 साल के लिए जावा लिख ​​रहे हैं और आपको नहीं पता कि डीबगर का उपयोग कैसे करें? (आपके कोड के माध्यम से कदम आपको दिखाएगा कि क्या हो रहा है और किस क्रम में)। –

+0

@BrianRoach निश्चित रूप से मैं डीबगर का उपयोग कर सकता हूं और मैंने javap -v -c bclass भी कोशिश की। लेकिन हर बार जब मैं जावा डेवलपर या साक्षात्कार के सवालों के लिए ऐसे कार्यों को देखता हूं, तो मैं आउटपुट की भविष्यवाणी करने और इसे समझने की कोशिश करता हूं, यह ऐसा क्यों काम करता है और यदि मैं कोड को थोड़ा संशोधित करता हूं तो क्या होता है। के माध्यम से कदम नियम और निष्पादन प्रक्रिया के कारण की व्याख्या नहीं करता है। – INlHELL

उत्तर

8

अनुक्रम है:

  1. मुख्य -> ​​"हैलो"
  2. मुख्य -> नया बी()
  3. बी() -> मुख्य() -> b.printVariable() -> परिवर्तनीय
  4. प्रारंभिक पर वापस सेट करें एनजी बी, तो परिवर्तनीय = शून्य होता है।

तो मूल रूप से, सुपर ऑब्जेक्ट मुख्य() कक्षा बी की किसी भी इंटिलाइज़ेशन घटनाओं से पहले बनाया गया है जिसका अर्थ है परिवर्तनीय = शून्य बाद में होता है। यह समझ में आता है क्योंकि अन्यथा बी मुख्य की शुरुआत को तोड़ सकता है।

जोशुआ ब्लोच अपनी प्रभावी जावा पुस्तक में बहुत अच्छी जमीन को कवर करता है कि कैसे सही खतरनाक विरासत सही है, मैं इसकी अनुशंसा करता हूं।

+0

स्पष्टीकरण के लिए बहुत बहुत धन्यवाद, आपने जिस पुस्तक का उल्लेख किया है उसके लिए बहुत बहुत धन्यवाद, मैं इसे एक और बार सावधानी से पढ़ूंगा। – INlHELL

2

सबसे पहले, आपको समझने की आवश्यकता है, जब आप variable = null; लिखते हैं तो क्या होता है। उस कोड को कब निष्पादित किया जाता है। यह मूल रूप से आउटपुट निर्धारित करता है।

शुरू करने से पहले, मुझे यह भी उल्लेख करना चाहिए कि जब आप class B का ऑब्जेक्ट बनाते हैं, तो printVariable() मुख्य वर्ग का कार्य नहीं कहा जाता है। इसके बजाय, बी के printVariable() को हमेशा कॉल किया जाएगा।

इसे ध्यान में रखते हुए, जब आपके पास variable = null है, तो बी के कन्स्ट्रक्टर के लिए निष्पादन शुरू हो जाएगा। पहले Main() को कॉल किया जाएगा, जो printVariable() विधि को कॉल करेगा। अंत में, variable=null, variable चर को ओवरराइट करने के लिए कहा जाएगा।

अन्य मामले में, जहां आप variable=null प्रारंभ नहीं करते हैं, printVariable() फ़ंक्शन द्वारा निर्धारित नहीं किया जाएगा, इसलिए आपको वह उम्मीद मिल जाएगी जो आप उम्मीद कर रहे थे।

सारांश में, इस बयान के निष्पादन के आदेश है, जब आप ऐसा करेंगे new B():

Main()  //super constructor 
    B#printVariable() 
    initializtion of variables in B's constructor (if any) [i.e. variable=null, if present] 
+0

आपको बहुत धन्यवाद, आपकी व्याख्या पूरी तरह से इस कोड को स्पष्ट करती है। जो मुझे नहीं मिला, यह संभव है कि इस तरह से क्षेत्र शुरू करना संभव हो: super_class-> method_of_child_class-> field_of_child_class और यह फ़ील्ड बच्चे के प्रारंभिकरण के दौरान ओवरराइट किया जा सकता है (यदि फ़ील्ड शून्य नहीं है) कक्षा। – INlHELL

1

यह एक अच्छा अभ्यास है! लेकिन जूनियर डेवलपर्स से पूछना उचित सवाल नहीं है। यह वरिष्ठ नागरिकों के लिए है।

public Main(String something){ 
printVariable(); 
} 

तो व्यक्ति का जवाब देंगे कि क्या होगा, तो तर्क को हटाने और मूल सवाल पूछने: लेकिन इस पाठ तकनीकी साक्षात्कार के दौरान उपयोगी बनाने के लिए, मैं इसे मुख्य के निर्माता के लिए एक तर्क जोड़कर संशोधित था । यदि व्यक्ति उत्तर नहीं देगा - जारी रखने की कोई आवश्यकता नहीं है - वह जूनियर है।

तुम भी वर्ग बी में संरक्षित क्वालीफायर को हटाने और पूछते हैं कि आप एक लक्ष्य इस व्यक्ति :)

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