2013-06-22 6 views
16

किसी विधि के अंदर स्थानीय आंतरिक कक्षा घोषित करते समय, अंतिम स्थिर स्ट्रिंग्स या इनट्स को शामिल करना कानूनी क्यों है लेकिन अन्य वस्तुओं को शामिल करने के लिए कानूनी नहीं है?विधि स्थानीय कक्षाओं में जावा अंतिम स्थिर घोषणा

उदाहरण के लिए:

class Outer { 
void aMethod() { 
    class Inner { 
     final static String name = "compiles"; 
     final static int ctr = 10; // compiles 
     final static Integer intThree = Integer.valueOf(3); // does not compile! 
     final static obj objConst = new Object(); // does not compile! 
    } 

    Inner inner = new Inner(); 
} 
} 

जब मैं इस संकलन, मैं निम्नलिखित हो:

InnerExample.java:6: inner classes cannot have static declarations 
     final static Integer outer = Integer.valueOf(3); 
          ^
InnerExample.java:7: inner classes cannot have static declarations 
     final static Object objConst = new Object(); 
          ^

क्यों भेद? क्या ऐसा इसलिए है क्योंकि स्ट्रिंग अपरिवर्तनीय है? यदि ऐसा है, तो Integer.valueOf() भी मान्य नहीं होगा?

+3

मुझे पूरा यकीन है कि यह "संकलित" है और 10 संकलन-समय निरंतर अभिव्यक्तियां हैं, लेकिन मुझे अभी तक जेएलएस नियम नहीं मिला है। –

उत्तर

17

ऐसा इसलिए है क्योंकि पहले दो स्थैतिक सदस्यों को आदिम प्रकार या प्रकार स्ट्रिंग के संकलन-समय स्थिरांक को सौंपा गया है।

Java Language Specification, section 8.1.3 से:

8.1.3। आंतरिक कक्षाएं और संलग्न उदाहरण

आंतरिक कक्षा स्थिर सदस्यों की घोषणा नहीं कर सकती है, जब तक कि वे निरंतर चर (§4.12.4), या संकलन-समय त्रुटि उत्पन्न न हो।

और 4.12.4 से:

आदिम प्रकार या प्रकार तार का एक चर, कि, अंतिम और एक संकलन समय निरंतर अभिव्यक्ति (§15.28) के साथ प्रारंभ है एक निरंतर चर कहा जाता है।

संपादित करें:

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

3

15.28 से एक संकलन समय निरंतर अभिव्यक्ति की परिभाषा पर विचार करें:

एक संकलन समय निरंतर अभिव्यक्ति एक अभिव्यक्ति या आदिम प्रकार के एक मूल्य एक स्ट्रिंग है कि अचानक पूरा नहीं करता है और संकेतित करते है का उपयोग कर बना है केवल निम्नलिखित:

आदिम प्रकार और प्रकार String (§3.10.1 का शाब्दिक, §3.10.2, §3.10.3 की
  • literals, §3.10.4, §3.10.5)
  • आदिम प्रकार के कलाकारों के साथ और टाइप करने के लिए String (§15.16)
  • डाले एकल ऑपरेटरों +, -, ~, और ! (लेकिन ++ या --) (§15.15.3, §15.15.4, §15.15.5, §15.15.6)
  • गुणात्मक ऑपरेटरों *, /, और % (§15।17)
  • additive ऑपरेटरों + और - (§15.18)
  • पारी ऑपरेटरों <<, >>, और >>> (§15.19)
  • संबंधपरक ऑपरेटर <, <=, >, और >= (लेकिन instanceof) (§15.20)
  • समानता ऑपरेटरों == और != (§15.21)
  • बिटवाइज़ और तार्किक ऑपरेटरों &, 012,, और | (§15.22)
  • सशर्त और ऑपरेटर && और सशर्त-या ऑपरेटर || (§15.23, §15.24)
  • त्रिगुट सशर्त ऑपरेटर ? : (§15.25)
  • Parenthesized भाव (§ 15.8.5) जिसका निहित अभिव्यक्ति निरंतर अभिव्यक्ति है।
  • सरल नाम (§6.5.6.1) जो स्थिर चर (§4.12.4) को संदर्भित करते हैं।
  • फॉर्म टाइपनाम के योग्य नाम (§6.5.6.2)। पहचानकर्ता जो निरंतर चर (§4.12.4) का संदर्भ देता है।

एक संकलन समय निरंतर अभिव्यक्ति की परिभाषा से के बाद, हम 4.12.4 है:

आदिम प्रकार का एक चर या टाइप String, कि final और एक compile- साथ प्रारंभ है समय निरंतर अभिव्यक्ति (§15.28), निरंतर चर कहा जाता है।

अंत में, 8.1.3 से:

इनर कक्षाएं स्थिर सदस्यों की घोषणा नहीं कर सकते हैं, जब तक कि वे लगातार चर (§4.12.4), या एक संकलन समय त्रुटि तब होती है।

5

पिछले उत्तर पर अधिक। असाइन किया गया मान संकलक द्वारा साबित होना चाहिए कि यह स्थिर है। जावा कंपाइलर आधार प्रकारों (int, float, आदि) और java.lang.String वर्ग के अर्थशास्त्र जानता है, लेकिन अन्य वर्गों नहीं। यह पहले दो उदाहरणों की निरंतरता को समझ सकता है।

कंपाइलर समझ में नहीं आता है कि Integer.valueOf (3) भी एक प्रभावशाली (वास्तव में स्थिर नहीं है, लेकिन हमेशा वही) मूल्य है, भले ही इंटीजर क्लास काम करता है, जानता है कि यह जानता है कि । संकलक इस तरह से व्यवहार करता है जैसे कि यह Integer.valueOf (x) था जो बदल सकता है। यह अच्छा होगा अगर जावा ने एनोटेशंस कॉन्सिस्टेंट जैसे एनोटेशन की पेशकश की, जिसने विधि व्यवहार को किसी दिए गए पैरामीटर के लिए स्थिर के रूप में घोषित किया, जैसे:

इंटीजर क्लास में: @ गोपनीय सार्वजनिक इंटीजर मानऑफ (int x) { ...}

अंतिम स्थैतिक पूर्णांक intThree = Integer.valueOf (3); // अब संकलन!

यह इंगित करता है कि विधि प्रत्येक आमंत्रण पर समान या समान वस्तु को समान तर्क मान देता है। चूंकि तर्क निरंतर अभिव्यक्ति है, इसलिए संकलक यह साबित कर सकता है कि परिणाम सभी उपयोगों में समान/बराबर होगा और इस प्रकार इसे निरंतर माना जा सकता है। इस मामले में इंटीजर एक ही ऑब्जेक्ट देता है, लेकिन यह बहुत अधिक इनपुट इनपुट मानों के लिए एक अलग (लेकिन बराबर) ऑब्जेक्ट लौटा सकता है (यानी यह 0 के करीब मानों को कैश करता है)।

ध्यान दें कि "नया" हमेशा एक अलग वस्तु देता है। नए ऑब्जेक्ट के लिए() यह हमेशा एक वस्तु है जो किसी अन्य वस्तु के बराबर नहीं है।

+0

यह एक शानदार स्पष्टीकरण है और दूसरे भाग का जवाब देने में मदद करता है, जो संकलन समय स्थिरांक के संबंध में Integer.valueOf() के संचालन को समझने का तरीका है। –

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