2011-08-25 18 views
9

मैं एक बहुत अजीब बग पर ठोकर खाई और मैं यह नहीं समझा सकता कि ऐसा क्यों होता है।जावा एनम स्थिरांक प्रारंभिक क्यों नहीं है?

import java.awt.Color; 

public class test { 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     System.out.println(MyEnum.CONSTANT1.get()); 
     System.out.println(MyEnum.CONSTANT2.get()); 
    } 

    private enum MyEnum { 
     CONSTANT1(staticMethod1()), 
     CONSTANT2(staticMethod2()); 

     private static final Color WHY_AM_I_NULL = new Color(255, 255, 255); 

     private final Color color; 

     private MyEnum(Color color) { 
      this.color = color; 
     } 

     public Color get() { 
      return color; 
     } 

     private static Color staticMethod1() { 
      return new Color(100, 100, 100); 
     } 

     private static Color staticMethod2() { 
      return WHY_AM_I_NULL; 
     } 
    } 

} 

परिणाम जब आप इस चलाते हैं:

java.awt.Color[r=100,g=100,b=100] 
null 

सवाल, क्यों एक दूसरे के मान शून्य होगा निम्नलिखित enum कल्पना कीजिए?

संशोधन: आप enum के अंदर एक निजी स्थिर कक्षा में WHY_AM_I_NULL डाल, तो यह पहले आरंभ नहीं हो जाता।

+0

Ammended नई अवलोकन –

+1

इसके अलावा, अगर आप एक विधि के माध्यम से निरंतर सीधे उपयोग करने का प्रयास करते हैं, ग्रहण एक त्रुटि दिखाता है। स्थैतिक विधि का उपयोग करते समय ऐसा नहीं है। यहां तक ​​कि FindBugs कोई समस्या नहीं दिखाता है! मुझे लगता है कि यह कम से कम –

उत्तर

12

समस्या यह है कि सभी स्थैतिक फ़ील्ड (और enum उदाहरण इस तरह गिना जाता है) उनके घोषित आदेश (specification) में प्रारंभ किए जाते हैं। तो जब CONSTANT2 तत्काल है, तो क्षेत्र WHY_AM_I_NULL अभी भी प्रारंभ नहीं हुआ है (और इसलिए null)।

जैसा कि आप enum उदाहरणों से पहले फ़ील्ड नहीं डाल सकते हैं, आपको अपनी इच्छित चीज़ों को करने का कोई अन्य तरीका ढूंढना होगा (उदाहरण के लिए, एनम क्लास के बाहर फ़ील्ड डालना)। यदि आप हमें बताते हैं, जो आप वास्तव में पूरा करना चाहते हैं, तो कोई और सुझाव दे सकता है।

संपादित करें: आप एक नेस्टेड वर्ग में WHY_AM_I_NULL डालें, तो इस वर्ग के क्षेत्रों जैसे ही कक्षा पहली से पहुंचा जाता है प्रारंभ किया जाएगा (अर्थात, staticMethod2 के निष्पादन के दौरान इस मामले में)।

+0

पर एक चेतावनी का हकदार है, मैं सिर्फ स्थिर होना चाहता हूं, जिसका उपयोग एनम निरंतर प्रारंभ में किया जाता है। यह काम करता है जब मैं निरंतर एक निजी स्थैतिक कक्षा में enum के अंदर डाल दिया। इस एनम के उपयोगकर्ता इस आंतरिक स्थिरता की परवाह नहीं करते हैं और मैं इसे एक से अधिक बार घोषित नहीं करना चाहता हूं (या यदि आपके पास रंग बनाने वाली विधि के रूप में एक से अधिक बार बनाया गया है) –

+1

इस मामले में मैं वास्तव में एक स्थैतिक घोंसला वर्ग का क्षेत्र-धारक वर्ग के रूप में उपयोग करता हूं। –

4

Enums संकलक सुविधा हैं। असल में कंपाइलर MyEnum नामक वर्ग बनाता है जिसमें 2 सार्वजनिक स्थैतिक फ़ील्ड CONSTANT1 और CONSTANT2 और अन्य कोड शामिल हैं।

स्टेटिक प्रारंभिकता अप-टू-डाउन किया जाता है, इसलिए कॉन्स्टेंट 2 बनाया गया है और स्थिर चर WHY_AM_I_NULL से पहले प्रारंभ किया गया है। यही कारण है कि CONSTANT2 प्रारंभ होने पर WHY_AM_I_NULL शून्य है।

1

ऐसा इसलिए है क्योंकि स्थैतिक फ़ील्ड (एनम मान सहित) को फ़ाइल में दिखाई देने के क्रम में प्रारंभ किया जाता है।

तो CONSTANT1, और CONSTANT2WHY_AM_I_NULL से पहले प्रारंभ हो, इसलिए CONSTANT2null साथ आरंभ नहीं हो जाता।

2

WHY_AM_I_NULL अशक्त जब staticMethod2 शुरू हो जाती है है - यह कैसे JLS प्रारंभ

एक अलग अनुक्रम में आप 100, 255 बजाय 100, null प्राप्त होता निर्दिष्ट करता है:

private static final Color WHY_AM_I_NULL = new Color(255, 255, 255); 
private enum MyEnum { 
    CONSTANT1(staticMethod1()), 
    CONSTANT2(staticMethod2()); 
    //... 
+0

-1। यह भी जवाब नहीं देता है कि एनम के अंदर एक फ़ील्ड क्यों शुरू नहीं किया गया है बल्कि यह दिखाकर समस्या को अलग कर रहा है कि यह कैसे enum के बाहर काम करता है। एक अन्य बिंदु यह ध्यान देने के लिए कि ** यह लिखने का सही जवाब कभी नहीं है "ऐसा होता है क्योंकि यह निर्दिष्ट किया गया था।" ** देखें [कैसे जवाब दें] (http://softwareengineering.stackexchange.com/help/how-to- जवाब) –

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