2012-07-24 15 views
7

मैंने इस बात को समझने में आधे घंटे बिताए हैं, मैंने अपना कोड ठीक करने में कामयाब रहा है, लेकिन मुझे पूरी तरह समझ नहीं आ रही है कि क्या हो रहा है और आश्चर्य हुआ कि कोई इस पर कुछ प्रकाश डाल सकता है।जावा स्टेटिक फील्ड प्रारंभिकरण

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

इस तरह यह पहले देखा गया था (जबकि अभी भी टूटा हुआ है);

//DBUtils.java 
public final class DBUtils { 

    private static DBConnection myDBConnection = spawnDBConnection(); 
    private static DBIndex myDBIndex = null; 

    private static DBConnection spawnDBConnection() { 
     //connect to the database 
     //assign a value to myDBIndex (by calling a method on the DBConnection object) <- IMPORTANT 
     //myDbIndex NOT NULL HERE 
     System.out.println("database connection completed"); 
     //return the DBConnection object 
    } 

    public static searchDB(String name) { 
     //use the myDBIndex to find a row and return it 
    } 
} 

तो संक्षेप में, मैं दोनों myDBConnection और myDBIndex को कोई मान निर्दिष्ट करने के लिए स्थिर spawnDBConnection() विधि का उपयोग कर रहा हूँ। यह पूरी तरह से काम करता है, मेरे प्रोग्राम से पहली आउटपुट लाइन हमेशा "डेटाबेस कनेक्शन पूर्ण हो जाती है", न ही myDBConnection या myDBIndex spawnDBConnection() विधि के अंत में शून्य हैं, सब कुछ ऐसा होना चाहिए।

मेरा बाहरी कार्यक्रम इस तरह दिखता है;

//DoSomethingUsefulWithTheDatabase.java 
public final class DoSomethingUsefulWithTheDatabase { 

    public static void main(String args[]) { 
     DBUtils.searchDB("John Smith"); //fails with NullPointerException on myDBIndex! 
    } 
} 

searchDB को इस कॉल में होता है के बाद spawnDBConnection समाप्त हो गया है, मैं मानक आउटपुट का इस्तेमाल किया है बड़े पैमाने पर इस दिखाने के लिए। हालांकि, एक बार खोज डीबी विधि के अंदर, myDBIndex का मान शून्य है! यह एक स्थिर क्षेत्र है, और यह spawnDBConnection के अंत तक शून्य नहीं था, कोई अन्य असाइनमेंट नहीं किया गया है, और अब यह शून्य है :(

सरल फिक्स "= null" को हटाने के लिए था इसलिए फ़ील्ड घोषणा अब दिखती है की तरह;

private static DBIndex myDBIndex; 

क्यों कि एक फर्क था कि मैं अच्छी तरह से इस एक से उलझन में हूँ

+4

बनाने पर विचार करें आपकी सांख्यिकी 'अंतिम'। इस तरह के आश्चर्य को खत्म करने के लिए आपको उन्हें एक बार असाइन करने के लिए मजबूर होना होगा। –

+4

यह एक भयानक दुःस्वप्न-एंटीपेटर्न है जो आप यहां कर रहे हैं। आप डेटाबेस कनेक्शन के अधिग्रहण के लिए क्लास प्रारंभिक युग्मन कर रहे हैं। –

+0

आपको स्थिर रूप से डीबीसी कनेक्शन शुरू नहीं करना चाहिए। क्या होगा यदि myDBConnection मर जाता है, तो क्या आप अपने कोड में DbUtils2 का उपयोग शुरू करने जा रहे हैं? –

उत्तर

13

क्योंकि myDBIndex को null का काम

private static DBConnection myDBConnection = spawnDBConnection(); 

उदा बाद किया जाता है यही कारण है कि ओवरराइड करता है spawnDBConnection

अनुक्रम में काम है:

  1. घोषित क्षेत्रों myDBConnection, myDBIndex
  2. प्रारंभ myDBConnection = spawnDBConnection();

    शामिल है, जो myDBConnection

  3. को spawnDBConnection और वापसी मान का काम बुला
  4. आरंभ करें(शून्य के साथ)

आपके दूसरे उदाहरण में, तीसरा चरण मौजूद नहीं है।

+0

इसे स्पष्ट करने के लिए धन्यवाद, यह अब सही समझ में आता है। किसी कारण से मेरे पास यह मेरे सिर में था कि 'सरल' असाइनमेंट के बाद कोई भी विधि कॉल होगी। – lynks

1

यह वही उत्पन्न static initalizer ब्लॉक में होता है:

static { 
    myDBConnection = spawnDBConnection(); 
    myDBIndex = null; 
} 
?।

मुझे आशा है कि यह अभी स्पष्ट है।

7

क्यों कि एक फर्क था? मैं इस से पूरी तरह उलझन में हूं।

spawnDBConnection के लिए प्रारंभकर्ता चल रहा था, तोmyDBIndex के लिए प्रारंभकर्ता चल रहा था। myDBIndex के लिए प्रारंभकर्ता को मान को शून्य में सेट करें। जैसा कि इस हुआspawnDBConnection एक गैर शून्य मान के लिए सेट के बाद, अंतिम परिणाम है कि यह शून्य था।

यह करने के लिए नहीं की कोशिश करो - यह एक विधि अन्य स्थैतिक चर सेट करने के लिए एक स्थिर प्रारंभकर्ता से बुलाया के लिए अजीब है।

+0

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

0

के रूप में मैं जानता हूँ कि का सवाल है, अगर आप अपने खेतों से पहले अपने विधि बताएं कि वह करता है काम, आरंभीकरण में, वर्ग शीर्ष से पार्स किया गया है:

public class DbUtils { 
    private static String spawnDBConnection() { 
     System.out.println("database connection completed"); 
     return "INIT"; 
    } 
    private static String myDBConnection = spawnDBConnection(); 
    private static int myDBIndex = 0; 

    public static void main(final String[] args) { 
     System.out.println(myDBConnection); 
    } 
} 

आउटपुट:

database connection completed 
INIT