2010-04-09 15 views
11

में रिटर्निंग यह मान्य कोड नहीं है। क्यों? क्या इसके लिए अच्छे कारण हैं? क्या कोई इस बारे में कुछ और जानता है?एक स्थिर प्रारंभकर्ता

इसलिए मुझे return क्यों करना चाहिए, इसका निर्माण करना समाप्त करना है।

धन्यवाद

+4

इन्हें स्थैतिक रचनाकारों के रूप में स्थिर प्रारंभिक कहा जाता है। खोजों में मदद के लिए बस इसे लिखना। – Oak

+0

@ ओक: धन्यवाद (15 वर्ण) –

उत्तर

15

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

तो, उदाहरण के लिए, जब आप एक वर्ग बारे में: फिर

class A { 
    static int x = 3; 
    static { 
     y = x * x; 
    } 
    static int z = x * x; 
} 

यह वास्तव में है के रूप में यदि आपके द्वारा लिखी गई:

class A { 
    static int x, y, z; 
    static { 
     x = 3; 
     y = x * x; 
     z = x * x; 
    } 
} 

अगर आप disassembly पर देखने की पुष्टि की है:

static {}; 
    Code: 
    0: iconst_3 
    1: putstatic  #5; //Field x:I 
    4: getstatic  #5; //Field x:I 
    7: getstatic  #5; //Field x:I 
    10: imul 
    11: putstatic  #3; //Field y:I 
    14: getstatic  #5; //Field x:I 
    17: getstatic  #5; //Field x:I 
    20: imul 
    21: putstatic  #6; //Field z:I 
    24: return 

तो यदि आप अपने स्थिर प्रारंभकर्ता के बीच में कहीं भी "वापसी" जोड़ते हैं तो यह भी होगा ई गणना की जा रही से ज़ेड को रोक दिया।

+1

मैं बस लिखने वाला था कि जब मैंने इसे देखा। यह भी ध्यान रखें कि आपके पास कक्षा में एकाधिक स्थिर प्रारंभिक ब्लॉक हो सकते हैं। –

+0

वास्तव में अच्छा जवाब, ओक। यह भी दिखाता है कि संकलन-समय त्रुटि देने के लिए एक स्थिर प्रारंभिक (जो कि टिप्पणी में उल्लिखित है) में एक अचानक पूर्णता को इतना बुरा क्यों माना जाता है। – jalopaba

2

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

10
  • कार्यक्रम प्रवाह हमेशा return की आवश्यकता के बिना जाने के लिए संरचित किया जा सकता है। (अपने उदाहरण एक else खंड में System.exit(0) डालने में वांछित परिणाम प्राप्त होगा)

  • में तुम सच में इसकी जरूरत है, तो आप एक स्थिर विधि में कोड के लिए कदम है और यह प्रारंभकर्ता से कॉल कर सकते हैं:

static { 
    staticInit(); 
} 

private static void staticInit() { 
    if (yesNo) { 
     System.out.println("Yes"); 
     return; 
    } 
    System.exit(0); 
} 

ध्यान दें कि यह एक स्थिर निर्माता नहीं है, यह एक स्थिर प्रारंभकर्ता है। कुछ भी नहीं बनाया जाता है।

+0

मुझे पता है कि आप इसे सरल 'अन्य' के साथ हल कर सकते हैं। लेकिन मैंने कहा कि यह एक बहुत बेवकूफ उदाहरण था। लेकिन यह सच है! –

+0

@ मार्टिजन Courteaux हाँ, मैं समझ गया कि। यही कारण है कि यह ब्रैकेट में है, बस मेरे सामान्यीकरण का एक उदाहरण है। – Bozho

1

JSL regarding static initializers से:

"यह एक स्थिर प्रारंभकर्ता के लिए एक संकलन समय त्रुटि (§14.1, §15.6) एक जाँच अपवाद (§11.2) के साथ अचानक पूरा करने के लिए सक्षम होने के लिए है यह एक compile- है। समय त्रुटि अगर एक स्थिर प्रारंभकर्ता सामान्य रूप से पूरा नहीं कर सकता (§14.21)। "

Abrupt completion (दूसरों के बीच): "कोई मूल्य नहीं के साथ वापसी", "किसी दिए गए मूल्य के साथ वापसी", आदि

तो एक स्थिर प्रारंभकर्ता में एक वापसी कथन एक "अचानक पूरा होने के" है और एक compile- का उत्पादन समय त्रुटि

+1

जेएसएल एक कारण निर्दिष्ट नहीं करता है, हालांकि, यह सवाल क्या है। – Oak

+1

मैं बस एक ही चीज़ पोस्ट करने वाला था, लेकिन मैं सोचने की कोशिश कर रहा था: एक स्थिर प्रारंभकर्ता का "अचानक पूरा होने" क्यों इतना बुरा है कि उन्होंने इसे संकलित त्रुटि बना दिया? –

+0

@ ओक: आप सही हैं, कोई कारण नहीं है। चश्मा कभी-कभी सिद्धांतों की तरह होते हैं। – jalopaba

0

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

ध्यान दें कि इसे आरंभ किए बिना बाइट-कोड लोड करना संभव है; Class.forName(String, boolean, ClassLoader) विधि देखें। यदि boolean पैरामीटर false है तो यह कक्षा लोड करेगा लेकिन इसे प्रारंभ नहीं करेगा। प्रोग्रामर अभी भी उस कक्षा के बारे में जानकारी को शुरू किए बिना कुछ प्रतिबिंबित कर सकता है। हालांकि, एक बार जब आप किसी स्थिर विधि को कॉल करके या इंस्टेंस को तुरंत चालू करके कक्षा का उपयोग करने का प्रयास करते हैं, तो JVM पहले इसे आरंभ करने के लिए आगे बढ़ेगा।

यदि कोई भी स्थिर प्रारंभकर्ता अचानक समाप्त हो जाता है - जो RuntimeException के साथ हो सकता है, तो कक्षा को अमान्य स्थिति में छोड़ा जाएगा। पहली बार, जेवीएम ExceptionInInitializeError फेंक देगा (ध्यान दें कि Error है जिसका अर्थ है कि इसे आंतरिक विफलता माना जाता है)। उस बिंदु से कक्षा का उपयोग करना संभव नहीं होगा - एक स्थिर विधि को कॉल करने या किसी ऑब्जेक्ट को तुरंत चालू करने का प्रयास करने के बाद आपको NoClassDefFoundError मिल जाएगा।

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

0

मैं कथन को फिर से व्यवस्थित करता हूं, जिससे इसे सरल/छोटा बना दिया जाता है। कभी भी एक अच्छा मामला नहीं होगा जहां दोनों की शाखाओं को वापसी की जरूरत है।

static { 
    if (!yesNo) 
     System.exit(0); // silently exiting a program is a bad idea!" 
    System.out.println("Yes"); 
} 
संबंधित मुद्दे