2009-04-27 12 views
5

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

class ParentClass 
{ 
    protected final static Set THE_SET = new Set() {{ 
     add("one"); 
     add("two"); 
     add("three"); 
    }}; 
} 


class SubClass extends ParentClass 
{ 
    protected final static Set THE_SET = new Set() {{ 
     add("four"); 
     add("five"); 
     add("six"); 
     union(ParentClass.THE_SET); /* [1] */ 
    }}; 
} 

सभी ठीक दिखते हैं, [1] रेखा को छोड़कर एक शून्य सूचक अपवाद का कारण बनता है। संभवतः इसका मतलब है कि उप-वर्ग में स्थिर प्रारंभिक अभिभावक वर्ग से पहले चलाया जा रहा है। यह मुझे आश्चर्यचकित कर दिया क्योंकि मैंने सोचा होगा कि यह पहले से किसी भी नए आयात में स्थैतिक ब्लॉक चलाएगा, पहले उपनिवेश में किसी भी को चलाने से पहले।

क्या मैं इस धारणा में सही हूं? क्या इस व्यवहार के आसपास नियंत्रण या काम करने का कोई तरीका है?

अद्यतन:

चीजें भी अजनबी हैं। मैंने कोशिश की यह बजाय (ध्यान दें 'नए ParentClass()' लाइन):

class ParentClass 
{ 
    public ParentClass() 
    { 
     System.out.println(THE_SET); 
    } 

    protected final static Set THE_SET = new Set() {{ 
     add("one"); 
     add("two"); 
     add("three"); 
    }}; 
} 


class SubClass extends ParentClass 
{ 
    protected final static Set THE_SET = new Set() {{ 
     System.out.println("a"); 
     new ParentClass(); 
     System.out.println("b"); 
     add("four"); 
     System.out.println("c"); 
     add("five"); 
     System.out.println("d"); 
     add("six"); 
     System.out.println("e"); 
     union(ParentClass.THE_SET); /* [1] */ 
     System.out.println("f"); 
    }}; 
} 

और उत्पादन अजीब है:

a 
["one", "two", "three"] 
b 
c 
d 
e 
Exception in thread "main" java.lang.ExceptionInInitializerError 
Caused by: java.lang.NullPointerException 

तो ParentClass initialised है, लेकिन उपवर्ग के लिए पहुँच नहीं है यह अपने स्थिर प्रारंभिक में।

उत्तर

7

क्या आप इसे पूरा करने की कोशिश कर रहे हैं? या आपको सेट इंटरफ़ेस के स्थानीय कार्यान्वयन की आवश्यकता है?

class ParentClass 
{ 
    protected final static Set THE_SET; 

    static { 
     THE_SET = new HashSet(); 
     THE_SET.add("one"); 
     THE_SET.add("two"); 
     THE_SET.add("three"); 
    } 
} 


class SubClass extends ParentClass 
{ 
    protected final static Set THE_SECOND_SET; 

    static { 
     THE_SECOND_SET = new HashSet(); 
     THE_SECOND_SET.add("four"); 
     THE_SECOND_SET.add("five"); 
     THE_SECOND_SET.add("six"); 
     union(ParentClass.THE_SET); /* [1] */ 
    } 
} 
+0

हाँ .. यह वही काम करता है। – izb

+1

मुझे लगता है कि एलीया इसे सही रखता है। यह initilization आदेश की समस्या नहीं है, बल्कि एक प्रकार का नाम संघर्ष है। – boutta

+0

मेरे असली कोड में, मेरे पास वास्तव में 3 कक्षाएं हैं जहां ए <-B <-C। अपवाद बी में था। दिलचस्प बात यह है कि प्रत्येक वर्ग को अपना स्वयं का सेट नाम सी को अपवाद ले जाता है लेकिन समस्या का समाधान नहीं करता है। यह बस इंगित करता है कि आदेश वास्तव में अप्रत्याशित है। – izb

3

कक्षाओं के बीच स्थिर प्रारंभिक आदेश की कोई गारंटी नहीं है। एक कक्षा के भीतर, वे स्रोत कोड के क्रम में भागते हैं।

यदि आप इसके बारे में सोचते हैं, तो कक्षाओं के बीच वास्तव में ऑर्डर नहीं हो सकता है, क्योंकि कक्षाओं को लोड होने पर आप नियंत्रण नहीं करते हैं; आप गतिशील रूप से कक्षा को लोड कर सकते हैं, या JVM लोड ऑर्डर को अनुकूलित कर सकता है।

+0

यदि कक्षा ए कक्षा बी को बढ़ाता है, तो वर्ग बी को लोड होने से पहले वर्ग ए को पूरी तरह से लोड नहीं किया जाना चाहिए? –

+0

मैंने सोचा होगा कि यह चारों ओर एक और तरीका होगा। निश्चित रूप से ए बी पर निर्भर करता है, इसलिए बी को पहले शुरू किया जाना चाहिए। – izb

+0

लेकिन प्राप्त करने के लिए (या बी के बारे में पता) इसे पहले कोड में जाना होगा। मतलब है कि बी में कोड से पहले एक स्थिर ब्लॉक कोड होगा, मुझे लगता है। –

2

यहां तक ​​कि यदि आपके पास extends ParentClass नहीं है, तो ParentClass का उपयोग करके इसे प्रारंभ करना चाहिए।

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

आपका जावा एमई कार्यान्वयन हो सकता है बग़ी (अनसुना नहीं)। भाग लें आपका पूरा ParentClass आपके ChildClass का संदर्भ देता है। या शायद कुछ अन्य एप्लिकेशन/लाइब्रेरी बग है।

एक संबंधित नोट पर, यदि आप नहीं -target 1.4 या बाद में, इनर क्लासों 'बाहरी इस जैसे ही आप उम्मीद कर सकते initialised नहीं कर दिया जाए। जैसा कि आपका कोड एक स्थिर संदर्भ में (तकनीकी रूप से) आंतरिक कक्षाओं का उपयोग करता है, इसलिए यह कोई समस्या नहीं होनी चाहिए।

यह भी दिलचस्प है कि स्थिर प्रारंभिकरण इस तरह की स्थितियों में थोड़ा उलझन में है, क्योंकि आपके पास वास्तव में चार वर्ग हैं।

0

के उत्पादन लाइन को देखते हुए [ "एक", "दो", "तीन"], यह मूल रूप से असंभव है कि ParentClass.THE_SET प्रारंभ नहीं किया गया है है।

बेशक, यह संभव है कि केवल एक क्लासलोडर शामिल न हो, लेकिन यह निश्चित रूप से विधि और रेखा संख्या को देखने में मददगार होगा जहां शून्य सूचक होता है।

+0

जे 2 एमई कस्टम क्लासलोडर्स की अनुमति नहीं देता .. यह बल्कि आदिम है। इसके अलावा, आउटपुट पर 'एफ' की कमी का तात्पर्य यह है कि यूनियन() लाइन पर त्रुटि हुई है जो इससे पहले है। – izb

2

उदाहरण प्रारंभिकरण (तथाकथित "डबल ब्रेस मुहावरे") के लिए अनाम कक्षाओं की अवधारणा का दुरुपयोग करना बंद करें।

+0

आप जानते हैं कि मैंने हमेशा सोचा था कि यह सिर्फ आसान वाक्यविन्यास था .. मुझे नहीं पता था कि यह वास्तव में एक अज्ञात वर्ग था। – izb

+0

यह सबसे बड़ा कारण है कि मैं इसे "मुहावरे" कहकर लोगों से नफरत करता हूं और इसे एक नाम देता हूं - यह भाषा की एक अलग विशेषता की तरह लगता है और वास्तव में क्या होता है अस्पष्ट करता है। –

-1

मुझे लगता है कि जावा पहेली पुस्तक या जावा युग के बारे में Google के यूट्यूब वीडियो में कुछ ऐसा ही लिखा गया था।

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