हम एक (गैर-स्थिर) आंतरिक वर्ग में स्थिर विधि क्यों नहीं कर सकते हैं?


142

हम गैर-स्थिर आंतरिक वर्ग में स्थैतिक विधि क्यों नहीं कर सकते?

अगर मैं आंतरिक वर्ग को स्थिर करता हूं तो यह काम करता है। क्यों?


4
क्योंकि अब जावा है कि पुराने कोबोल :) है
सत्र

लब्बोलुआब यह है: क्योंकि उन्होंने इसे अभी तक लागू नहीं किया है।
इंट्रेपिडिस

1
Is नॉन-स्टैटिक इनर ’एक टॉटोलॉजी है।
लोरेन का मार्किस

यदि आप अपने आंतरिक वर्ग को दूसरों के सामने नहीं रखना चाहते हैं और आशा करते हैं कि इसमें स्थैतिक विधियाँ शामिल हैं, तो आप संशोधक को "निजी" और "स्थैतिक" दोनों को आंतरिक कक्षा में रख सकते हैं।
विली जेड

एक आंतरिक वर्ग स्थिर नहीं परिभाषा से है। आपके पास एक स्थिर नेस्टेड / सदस्य वर्ग और एक गैर-स्थिर नेस्टेड / सदस्य वर्ग हो सकता है। उत्तरार्द्ध को एक आंतरिक वर्ग के रूप में भी जाना जाता है। (संदर्भ: जेएलएस की धारा 8.1.3 में कहा गया है "एक आंतरिक वर्ग एक नेस्टेड वर्ग है जो स्पष्ट रूप से या अंतर्निहित रूप से घोषित नहीं किया गया है static।")
इरविन बोलविएट

जवाबों:


111

क्योंकि आंतरिक वर्ग का एक उदाहरण अंतर्निहित रूप से अपने बाहरी वर्ग के उदाहरण के साथ जुड़ा हुआ है, यह स्वयं किसी भी स्थिर तरीकों को परिभाषित नहीं कर सकता है। चूंकि एक स्थिर नेस्टेड वर्ग सीधे उदाहरण के लिए संदर्भित नहीं कर सकता है चर या इसके संलग्न वर्ग में परिभाषित तरीके, यह केवल एक ऑब्जेक्ट संदर्भ के माध्यम से उनका उपयोग कर सकता है, यह एक स्थिर नेस्टेड वर्ग में स्थिर तरीकों की घोषणा करने के लिए सुरक्षित है।


7
मुझे पता है कि एक आंतरिक वर्ग अपने बाहरी वर्ग के उदाहरण के साथ जुड़ा हुआ है और मुझे पता है कि यह थोड़े बेकार है कि हम एक आंतरिक वर्ग के भीतर स्थैतिक सदस्यों की घोषणा करने में सक्षम हो जाते हैं लेकिन मैं अभी भी पूछ रहा हूं कि कोई आंतरिक वर्ग स्थैतिक सदस्यों की घोषणा क्यों नहीं कर सकता है?
करीम

15
C ++ में आपके पास हो सकता है, इसलिए यह जावा भाषा में एक बग है।
औद्योगिक-एंटीडिप्रेसेंट

39
बग शब्द ... मुझे नहीं लगता कि इस शब्द का मतलब है कि आप क्या सोचते हैं इसका मतलब है।
सेठ नेल्सन

24
एक अधिक उपयुक्त वाक्यांश 'मदरब्रुक के रूप में कष्टप्रद' होगा। समझ में नहीं आता कि जावा इसके लिए अनुमति क्यों नहीं देता। कभी-कभी, मैं मूल वर्ग के गुणों का उपयोग करने के लिए एक आंतरिक वर्ग चाहता हूं, लेकिन बेहतर नामस्थान के लिए स्थैतिक तरीके रखता हूं। क्या इसमें कुछ गड़बड़ है? :(
अंगद

6
बिल्कुल सही। मैं एक उपयोगिता आंतरिक वर्ग लिखना चाहता हूं। इसके कुछ तरीके बाहरी वर्ग तक पहुँच से लाभान्वित होंगे, इसलिए मैं इसे स्थिर नहीं बना सकता, लेकिन इसके कुछ तरीके सिर्फ उपयोगिता कार्य हैं। मैं A.B.sync(X)(A के भीतर से) कॉल या भी क्यों नहीं कर सकता B.sync(x)?
एडवर्ड फॉक

44

एक गैर-स्थिर आंतरिक वर्ग में एक स्थिर विधि की अनुमति देने के लिए बहुत अधिक बिंदु नहीं है; आप इसे कैसे एक्सेस करेंगे? आप बाहरी कक्षा के उदाहरण के बिना (कम से कम शुरू में) एक गैर-स्थिर आंतरिक वर्ग उदाहरण तक पहुँच नहीं सकते। एक गैर-स्थिर आंतरिक वर्ग बनाने के लिए कोई विशुद्ध रूप से स्थिर तरीका नहीं है।

बाहरी वर्ग के लिए Outer, आप test()इस तरह एक स्थिर विधि का उपयोग कर सकते हैं :

Outer.test();

एक स्थिर आंतरिक वर्ग के लिए Inner, आप इसकी स्थैतिक विधि innerTest()को इस तरह एक्सेस कर सकते हैं :

Outer.Inner.innerTest();

हालांकि, यदि Innerस्थिर नहीं है , तो विधि को संदर्भित करने के लिए अब कोई विशुद्ध रूप से स्थिर तरीका नहीं है innertest। गैर-स्थिर आंतरिक कक्षाएं उनके बाहरी वर्ग के एक विशिष्ट उदाहरण से जुड़ी होती हैं। एक फ़ंक्शन स्थिर से भिन्न होता है, जिसमें एक संदर्भ को Outer.Inner.CONSTANTइस तरह से अस्पष्ट होने की गारंटी दी जाती है कि फ़ंक्शन कॉल Outer.Inner.staticFunction();नहीं है। मान लीजिए कि आपके पास Inner.staticFunction()वह कॉल है getState(), जिसे परिभाषित किया गया है Outer। यदि आप उस स्थिर कार्य को लागू करने का प्रयास करते हैं, तो अब आपके पास इनर वर्ग के लिए एक अस्पष्ट संदर्भ है। यही है, आप आंतरिक वर्ग के किस उदाहरण पर स्थिर कार्य को लागू करते हैं? यह मायने रखता है। देखें, बाहरी वस्तु के निहित संदर्भ के कारण, उस स्थिर विधि को संदर्भित करने का कोई सही तरीका नहीं है।

पॉल बेलोरा सही है कि भाषा डिजाइनर इसकी अनुमति दे सकते थे। फिर उन्हें गैर-स्टेटिक इनर क्लास के स्थैतिक तरीकों में बाहरी वर्ग के लिए निहित संदर्भ के किसी भी उपयोग को सावधानीपूर्वक अस्वीकार करना होगा। इस बिंदु पर, आंतरिक वर्ग होने के नाते इसका क्या मूल्य है यदि आप बाहरी वर्ग को, सांख्यिकीय रूप से छोड़कर, संदर्भ नहीं दे सकते हैं? और अगर स्थिर पहुंच ठीक है, तो पूरे आंतरिक वर्ग को स्थिर क्यों घोषित नहीं किया जाता है? यदि आप केवल आंतरिक वर्ग को ही स्थिर बनाते हैं, तो आपके पास बाहरी वर्ग के लिए कोई निहित संदर्भ नहीं है, और अब आपके पास यह अस्पष्टता नहीं है।

यदि आपको वास्तव में एक गैर-स्थिर आंतरिक वर्ग पर स्थिर तरीकों की आवश्यकता है , तो आपको संभवतः अपने डिजाइन को पुनर्विचार करने की आवश्यकता है।


6
-1 मुझे यहाँ आपके द्वारा लिए गए कोण से असहमत होना होगा। निश्चित रूप से हम एक आंतरिक वर्ग प्रकार उल्लेख कर सकते हैं, उदाहरण के लिए Outer.Inner i = new Outer().new Inner();इसके अलावा, इनर क्लासों कर रहे हैं स्थिर घोषित करने के लिए अनुमति दी स्थिरांक JLS §15.28 के अनुसार।
पॉल बेलोरा

2
हां, आंतरिक कक्षाएं स्थिर स्थिरांक घोषित कर सकती हैं । इसका स्थैतिक तरीकों से कोई लेना-देना नहीं है! जबकि आप गैर-सांख्यिकीय रूप से एक स्थिर पद्धति का उल्लेख कर सकते हैं, यह हतोत्साहित करता है। सभी कोड गुणवत्ता वाले उपकरण उस तरह के संदर्भ में और अच्छे कारण से शिकायत करते हैं। और आपने मेरी बात को याद किया। मैंने कभी नहीं कहा कि एक स्थिर आंतरिक वर्ग को संदर्भित करने का कोई तरीका नहीं है। मैंने कहा कि गैर-स्थिर बाहरी वर्ग के आंतरिक वर्ग की स्थैतिक पद्धति को संदर्भित करने के लिए कोई STATIC तरीका नहीं है। इस प्रकार, इसे संदर्भित करने के लिए कोई प्रॉपर तरीका नहीं है।
एडी

25
"गैर-स्थिर आंतरिक वर्ग में एक स्थिर विधि की अनुमति देने के लिए बहुत अधिक बिंदु नहीं है, आप इसे कैसे एक्सेस करेंगे?" आप Outer.Inner.staticMethod()वैसे ही कॉल करेंगे जैसे आप एक्सेस कर सकते हैं Outer.Inner.CONSTANT। "आप एक्सेस नहीं कर सकते ... बाहरी वर्ग के उदाहरण के बिना एक गैर-स्थिर आंतरिक वर्ग उदाहरण।" आपको एक उदाहरण की आवश्यकता क्यों होगी? आपको Outerकॉल करने के लिए किसी इंस्टेंस की आवश्यकता नहीं है Outer.staticMethod()। मुझे पता है कि यह नाइटपिक है, लेकिन मेरा कहना यह है कि इस तरह से आपके जवाब को फ्रेम करने का कोई मतलब नहीं है। अगर वे चाहें तो भाषा डिजाइनरों को इसकी अनुमति नहीं दे सकते थे।
पॉल बेलोरा

1
के बीच का अंतर है Outer.Inner.CONSTANTऔर Outer.Inner.staticMethod()यह है कि किसी स्थिरांक के संदर्भ में तात्कालिक रूप से उस उदाहरण को संदर्भित करने का कोई मौका नहीं है जिसमें त्वरित रूप से संदर्भित Outerकिया Innerगया था। सभी संदर्भ Outer.staticMethod()एक ही सटीक स्थिति को साझा करने के लिए । सभी संदर्भ Outer.Inner.CONSTANTएक ही सटीक स्थिति को साझा करने के लिए । हालांकि, संदर्भ Outer.Inner.staticMethod()अस्पष्ट हैं: प्रत्येक उदाहरण में बाहरी वर्ग के निहित संदर्भ के कारण "स्थिर" स्थिति वास्तव में स्थिर नहीं है Inner। इसे एक्सेस करने के लिए वास्तव में असंदिग्ध, स्थिर तरीका नहीं है।
एडी

3
@ ईडीआई आप स्थैतिक विधि में फ़ील्ड को संदर्भित नहीं कर सकते, इसलिए निहित क्षेत्र को संदर्भित करने में असमर्थता से संबंधित कोई संघर्ष नहीं है Outer.this। मैं जावा भाषा डिजाइनरों से सहमत हूं कि आंतरिक कक्षाओं में स्थिर तरीकों या गैर-अंतिम स्थिर क्षेत्रों की अनुमति देने का कोई कारण नहीं है, क्योंकि एक आंतरिक वर्ग में सब कुछ संलग्न वर्ग के संदर्भ में होना चाहिए।
थियोडोर मर्डॉक

20

मेरे पास एक सिद्धांत है, जो सही हो भी सकता है और नहीं भी।

सबसे पहले, आपको कुछ चीजों के बारे में पता होना चाहिए कि जावा में आंतरिक कक्षाएं कैसे लागू की जाती हैं। मान लीजिए कि आपको यह वर्ग मिला है:

class Outer {
    private int foo = 0;
    class Inner implements Runnable {
        public void run(){ foo++; }
    }
    public Runnable newFooIncrementer(){ return new Inner(); }
}

जब आप इसे संकलित करते हैं, तो उत्पन्न बाइटकोड ऐसा लगेगा जैसे आपने कुछ ऐसा लिखा हो:

class Outer {
    private int foo = 0;
    static class Inner implements Runnable {
        private final Outer this$0;
        public Inner(Outer outer){
            this$0 = outer;
        }
        public void run(){ this$0.foo++; }
    }
    public Runnable newFooIncrementer(){ return new Inner(this); }
}

अब, यदि हमने गैर-स्थिर आंतरिक कक्षाओं में स्थिर तरीकों की अनुमति दी है, तो आप ऐसा कुछ करना चाह सकते हैं।

class Outer {
    private int foo = 0;
    class Inner {
        public static void incrFoo(){ foo++; }
    }
}

... जो काफी हद तक उचित लगता है, क्योंकि Innerलगता है कि प्रति वर्ग एक अवतार है Outer। लेकिन जैसा कि हमने ऊपर देखा, गैर-स्थिर आंतरिक वर्ग वास्तव में स्थैतिक "आंतरिक" वर्गों के लिए सिंटैक्टिक शुगर हैं, इसलिए अंतिम उदाहरण लगभग बराबर होगा:

class Outer {
    private int foo = 0;
    static class Inner {
        private final Outer this$0;
        public Inner(Outer outer){
            this$0 = outer;
        }
        public static void incrFoo(){ this$0.foo++; }
    }
}

... जो स्पष्ट रूप से काम नहीं करेगा, क्योंकि this$0गैर-स्थिर है। इस प्रकार की व्याख्या करता है कि स्थिर तरीकों की अनुमति क्यों नहीं दी जाती है (हालाँकि आप तर्क दे सकते हैं कि आप तब तक स्थैतिक विधियों की अनुमति दे सकते हैं जब तक वे संलग्न वस्तु का संदर्भ नहीं देते हैं), और आपके पास गैर-अंतिम स्थिर फ़ील्ड क्यों नहीं हो सकते ( यदि प्रति-स्थिर "साझा राज्य" से अलग-अलग वस्तुओं से गैर-स्थिर आंतरिक वर्गों के उदाहरणों को काउंटर-सहज होगा। यह भी बताता है कि अंतिम फ़ील्ड को अनुमति क्यों दी जाती है (जब तक वे संलग्न वस्तु का संदर्भ नहीं देते हैं)।


7
लेकिन यह एक सामान्य "स्थिर संदर्भ से गैर-स्थिर चर को एक्सेस करने का प्रयास" प्रकार की त्रुटि है - यदि कोई शीर्ष स्तर का स्थिर तरीका है, तो यह स्वयं के वर्ग के आवृत्ति चर तक पहुंचने का प्रयास करने से अलग नहीं है।
लॉरेंस डोल

2
मैं इस awser को पसंद करता हूं क्योंकि यह वास्तव में बताता है कि तकनीकी रूप से यह संभव क्यों नहीं है, भले ही यह वाक्यात्मक रूप से संभव हो सकता है।
LoPoBo

@gustafc, मुझे लगता है कि यह एक उत्कृष्ट व्याख्या थी। लेकिन जैसा कि लॉरेंस बताते हैं, फू के संदर्भ के कारण यह केवल एक विफलता है, जो स्थिर नहीं है। लेकिन क्या होगा अगर मैं public static double sinDeg(double theta) { ... }एक आंतरिक गणित उपयोगिताओं वर्ग लिखना चाहता था ?
एडवर्ड फॉक

6

एकमात्र कारण "नहीं होना चाहिए" है, इसलिए इसे समर्थन करने के लिए परेशान क्यों हैं?

सिंथेटिक रूप से, एक आंतरिक वर्ग को स्थिर सदस्य होने से प्रतिबंधित करने का कोई कारण नहीं है। हालांकि एक उदाहरण के एक उदाहरण के Innerसाथ जुड़ा हुआ है Outer, यह अभी भी संभव है Outer.Inner.myStaticकि Innerअगर जावा ऐसा करने का फैसला करता है , तो एक स्थिर सदस्य को संदर्भित करने के लिए उपयोग करना संभव है ।

यदि आपको सभी उदाहरणों के बीच कुछ साझा करने की आवश्यकता है Inner, तो आप उन्हें Outerस्थिर सदस्यों के रूप में डाल सकते हैं। यह आपके द्वारा स्थैतिक सदस्यों का उपयोग करने से बदतर नहीं है Inner, जहां Outerअभी भी किसी भी निजी सदस्य का उपयोग कर सकते हैं Inner(इनकैप्सुलेशन में सुधार नहीं करता है)।

यदि आपको Innerएक outerवस्तु द्वारा बनाए गए सभी उदाहरणों के बीच कुछ साझा करने की आवश्यकता है , तो उन्हें Outerसामान्य सदस्यों के रूप में कक्षा में रखने के लिए अधिक समझ में आता है ।

मैं इस राय से सहमत नहीं हूं कि "एक स्थिर नेस्टेड क्लास सिर्फ एक उच्च स्तरीय वर्ग है"। मुझे लगता है कि बाहरी वर्ग के हिस्से के रूप में वास्तव में एक स्थिर नेस्टेड वर्ग / आंतरिक वर्ग के संबंध में बेहतर है, क्योंकि वे बाहरी वर्ग के निजी सदस्यों तक पहुंच सकते हैं। और बाहरी वर्ग के सदस्य "आंतरिक वर्ग के सदस्य" भी हैं। इसलिए आंतरिक वर्ग में स्थिर सदस्य का समर्थन करने की आवश्यकता नहीं है। बाहरी वर्ग में एक साधारण / स्थिर सदस्य पर्याप्त होगा।


इनर क्लासेस "मस्ट" नहीं हैं। हालाँकि, जैसा कि भाषा आंतरिक कक्षाओं को प्रदान करती है , उन्हें इसका पूर्ण और सार्थक कार्यान्वयन प्रदान करना चाहिए।
इंट्रेपिडिस

4

से: https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html

उदाहरण के तरीकों और चर के साथ, एक आंतरिक वर्ग अपने संलग्न वर्ग की एक आवृत्ति के साथ जुड़ा हुआ है और उस वस्तु के तरीकों और क्षेत्रों तक सीधी पहुंच है। इसके अलावा, क्योंकि एक आंतरिक वर्ग एक उदाहरण के साथ जुड़ा हुआ है, यह स्वयं किसी भी स्थिर सदस्य को परिभाषित नहीं कर सकता है।

ओरेकल की व्याख्या सतही और हाथ से है। चूँकि किसी आंतरिक वर्ग के भीतर स्थैतिक सदस्यों को प्रीमेच करने का कोई तकनीकी या वाक्यगत कारण नहीं है (यह अन्य भाषाओं जैसे सी # में अनुमति है) जावा डिजाइनरों की प्रेरणा की संभावना वैचारिक स्वाद और / या तकनीकी सुविधा का मामला था।

यहाँ मेरा अनुमान है:

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

स्थैतिक सदस्यों की बहुत प्रकृति (जो वस्तु-उन्मुख नहीं हैं) आंतरिक वर्गों की उदाहरण-निर्भर आत्मा के साथ टकराव (जो कि वस्तु-उन्मुख है) क्योंकि आप बाहरी वर्ग उदाहरण के बिना किसी आंतरिक वर्ग के स्थिर सदस्य को संदर्भित / कॉल कर सकते हैं। योग्य आंतरिक वर्ग नाम का उपयोग करना।

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

दूसरी ओर, स्थैतिक स्थिरांक द्वारा ऐसा कोई अपराध नहीं किया जाता है, जो सार्थक रूप से राज्य का गठन नहीं करता है और इसलिए ये स्वीकार्य हैं। उदाहरण-निर्भर आत्मा के साथ अधिकतम स्थिरता के लिए स्थैतिक स्थिरांक को मना क्यों नहीं किया जाता है ? शायद इसलिए कि स्थिरांक को आवश्यकता से अधिक मेमोरी नहीं लेनी पड़ती है (यदि उन्हें गैर-स्थिर होने के लिए मजबूर किया जाता है तो उन्हें हर आंतरिक वर्ग उदाहरण में कॉपी किया जाता है जो संभावित रूप से बेकार है)। अन्यथा मैं अपवाद के कारण की कल्पना नहीं कर सकता।

यह रॉक-सॉलिड रीज़निंग नहीं हो सकता है लेकिन IMO यह मामले पर ओरेकल की सरसरी टिप्पणी का सबसे अधिक अर्थ देता है।


3

संक्षिप्त उत्तर: मानसिक मॉडल अधिकांश प्रोग्रामर के पास होता है कि कैसे कार्य करता है जो कि javac द्वारा उपयोग किया जाने वाला मॉडल नहीं है। अधिक सहज मॉडल से मेल खाने से जेवैक काम करने के लिए एक बड़े बदलाव की आवश्यकता होगी।

मुख्य कारण यह है कि आंतरिक वर्गों में स्थिर सदस्य वांछनीय हैं कोड सफाई के लिए - एक स्थिर सदस्य जिसका उपयोग केवल एक आंतरिक वर्ग द्वारा किया जाता है, उसे बाहरी कक्षा में रखा जाना चाहिए। विचार करें:

class Outer {
   int outID;

   class Inner {
      static int nextID;
      int id = nextID++;

      String getID() {
         return outID + ":" + id;
      }
   }
}

इस बात पर विचार करें कि जब मैं अयोग्य पहचानकर्ता "outID" का उपयोग करता हूं तो getID () में क्या चल रहा है। यह पहचानकर्ता जिस क्षेत्र में दिखाई देता है वह कुछ इस प्रकार है:

Outer -> Inner -> getID()

यहाँ, फिर से क्योंकि यह है कि कैसे javac काम करता है, गुंजाइश के "बाहरी" स्तर में बाहरी दोनों और स्थिर सदस्य शामिल हैं। यह भ्रामक है क्योंकि हमें आमतौर पर एक वर्ग के स्थिर हिस्से को एक और स्तर के दायरे के रूप में माना जाता है:

Outer static -> Outer instance -> instanceMethod()
         \----> staticMethod()

इसके बारे में सोचने के तरीके में, निश्चित रूप से staticMethod () केवल Outer के स्थिर सदस्यों को देख सकता है। लेकिन अगर ऐसा होता है कि कैसे javac काम करता है, तो एक स्थिर चर में उदाहरण चर का संदर्भ देने से "नाम हल नहीं किया जा सकता" त्रुटि हो सकती है। वास्तव में क्या होता है कि यह नाम स्कोप में पाया जाता है, लेकिन फिर एक अतिरिक्त स्तर की जाँच होती है और यह पता चलता है कि नाम एक उदाहरण के संदर्भ में घोषित किया गया था और इसे एक स्थिर संदर्भ से संदर्भित किया जा रहा है।

ठीक है, यह आंतरिक वर्गों से कैसे संबंधित है? स्वाभाविक रूप से, हमें लगता है कि कोई कारण नहीं है कि भीतर की कक्षाओं में एक स्थिर गुंजाइश नहीं हो सकती है, क्योंकि हम इस तरह काम कर रहे दायरे का चित्रण कर रहे हैं:

Outer static -> Outer instance -> Inner instance -> getID()
         \------ Inner static ------^

दूसरे शब्दों में, आंतरिक वर्ग में स्थिर घोषणाएं और बाहरी वर्ग में उदाहरण घोषणाएं दोनों आंतरिक वर्ग के उदाहरण संदर्भ के दायरे में हैं, लेकिन इनमें से कोई भी वास्तव में दूसरे में निहित नहीं है; दोनों बजाय बाहरी के स्थिर दायरे में निहित हैं।

बस यह नहीं है कि कैसे काम करता है javac - स्थैतिक और उदाहरण के सदस्यों के लिए गुंजाइश का एक ही स्तर है, और गुंजाइश हमेशा सख्ती से घोंसला बनाती है। यहां तक ​​कि विरासत को उप-केंद्र में घोषणाओं की नकल करने के बजाय ब्रांचिंग और सुपरक्लास गुंजाइश की खोज करके लागू किया जाता है।

आंतरिक वर्गों के स्थिर सदस्यों का समर्थन करने के लिए javac को या तो स्थैतिक और उदाहरण स्कैप को विभाजित करना होगा और ब्रांचिंग और रिजनिंग स्कोप पदानुक्रमों का समर्थन करना होगा, या सभी स्तरों पर संदर्भ के प्रकार को ट्रैक करने के लिए अपने सरल बूलियन "स्थिर संदर्भ" विचार को बदलना होगा। मौजूदा दायरे में नेस्टेड क्लास।


मुझे लगता है कि गैर-स्थिर आंतरिक वर्गों को गैर-स्थिर स्थैतिक सदस्यों की अनुमति देने के साथ एक और मौलिक कठिनाई यह है कि ऐसे सदस्यों की घोषणा करने वाले प्रोग्रामर उन्हें बाहरी वर्ग के उदाहरणों के लिए बाध्य करने का इरादा कर सकते हैं, या उन्हें वास्तव में स्थिर होना चाहिए। ऐसे मामलों में जहां एक निर्माण - अगर कानूनी - समझदारी से दो अलग-अलग चीजों के अर्थ के रूप में निर्दिष्ट किया जा सकता है, और जहां उन दोनों चीजों को अन्य असंदिग्ध तरीकों से व्यक्त किया जा सकता है, तो उस निर्माण को अवैध होने के रूप में निर्दिष्ट करना अक्सर इसे निर्दिष्ट करने से बेहतर है। या तो अर्थ है।
सुपरकैट

3

हम गैर-स्थिर आंतरिक वर्ग में स्थैतिक विधि क्यों नहीं कर सकते?

नोट: एक गैर-स्थिर नेस्टेड वर्ग को आंतरिक वर्ग के रूप में जाना जाता है, इसलिए आपके पास ऐसा नहीं है non-static inner class

बाहरी वर्ग के अनुरूप उदाहरण के बिना एक आंतरिक वर्ग का कोई अस्तित्व नहीं है। एक आंतरिक वर्ग संकलित समय स्थिरांक के अलावा स्थिर सदस्यों की घोषणा नहीं कर सकता है। अगर इसकी अनुमति होती तो अर्थ के बारे में अस्पष्टता होती static। उस मामले में कुछ निश्चित भ्रम रहे होंगे:

  1. क्या इसका मतलब वीएम में केवल एक उदाहरण है?
  2. या केवल एक उदाहरण प्रति बाहरी वस्तु?

यही कारण है कि डिजाइनरों ने शायद इस मुद्दे को बिल्कुल नहीं संभालने का निर्णय लिया।

अगर मैं आंतरिक वर्ग को स्थिर करता हूं तो यह काम करता है। क्यों ?

फिर से आप एक आंतरिक वर्ग को स्थिर नहीं बना सकते हैं बल्कि आप एक स्थिर वर्ग को नेस्टेड घोषित कर सकते हैं। उस स्थिति में यह नेस्टेड वर्ग वास्तव में बाहरी वर्ग का हिस्सा है और इसमें बिना किसी मुद्दे के स्थिर सदस्य हो सकते हैं।


3

इस विषय ने कई लोगों का ध्यान आकर्षित किया है, फिर भी मैं सबसे सरल शब्दों में समझाने की कोशिश करूंगा।

सबसे पहले, http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.1 के संदर्भ में , एक क्लास या इंटरफ़ेस को पहली घटना / आह्वान से तुरंत पहले शुरू किया जाता है। किसी भी सदस्य जो स्थैतिक कीवर्ड से पहले है।

  1. इसलिए, अगर हम एक आंतरिक वर्ग के भीतर एक स्थिर सदस्य के साथ रखते हैं, तो यह आंतरिक वर्ग के आरंभ को जन्म देगा, जरूरी नहीं कि बाहरी / संलग्न वर्ग। इसलिए, हम वर्ग आरंभीकरण अनुक्रम में बाधा डालते हैं।

  2. इस तथ्य पर भी विचार करें कि एक गैर-स्थिर आंतरिक वर्ग एक संलग्नक / बाहरी वर्ग के उदाहरण के साथ जुड़ा हुआ है। तो, एक उदाहरण के साथ जुड़ने का मतलब होगा, कि आंतरिक वर्ग एक बाहरी वर्ग उदाहरण के अंदर मौजूद होगा और उदाहरणों के बीच अलग होगा।

बिंदु को सरल करते हुए, स्थैतिक सदस्य तक पहुंचने के लिए हमें एक बाहरी वर्ग की एक आवृत्ति की आवश्यकता होती है, जिसमें से हमें फिर से गैर-स्थिर आंतरिक वर्ग का एक उदाहरण बनाने की आवश्यकता होगी। स्थैतिक सदस्यों को उदाहरणों के लिए बाध्य नहीं माना जाता है और इसलिए आपको संकलन त्रुटि मिलती है।


2

एक आंतरिक वर्ग एक स्थिर नेस्टेड वर्ग से पूरी तरह से अलग है, हालांकि दोनों वाक्यविन्यास में समान हैं। स्टैटिक नेस्टेड क्लासेस केवल ग्रुपिंग के लिए एक साधन हैं जबकि इनर क्लासेस का एक मजबूत जुड़ाव है - और इनका सभी मूल्यों तक पहुँच - इनका बाहरी वर्ग। आपको यह सुनिश्चित करना चाहिए कि आप एक आंतरिक वर्ग का उपयोग क्यों करना चाहते हैं और फिर इसे प्राकृतिक रूप से आना चाहिए, जिसे आपको उपयोग करना है। यदि आपको एक स्थिर विधि की घोषणा करने की आवश्यकता है तो यह संभवतः एक स्थिर नेस्टेड वर्ग है जिसे आप चाहते हैं।


बेनेडिक्ट, जब आप कहते हैं कि "स्टैटिक नेस्टेड क्लासेस केवल समूह बनाने का एक साधन है" तो आपका क्या मतलब है?
अंकुर

0

मान लीजिए कि बाहरी वर्ग के दो उदाहरण हैं और इन दोनों के पास आंतरिक वर्ग का तात्पर्य है। यदि आंतरिक वर्ग में एक स्थिर सदस्य है तो यह उस सदस्य की केवल एक प्रति को ढेर क्षेत्र में रखेगा। इस मामले में बाहरी वर्ग की दोनों वस्तुओं को संदर्भित करेगा। एकल प्रति और वे इसे एक साथ बदल सकते हैं। यह "डर्टी रीड" स्थिति पैदा कर सकता है इसलिए इस जावा को रोकने के लिए इस प्रतिबंध को लागू किया गया है। इस तर्क का समर्थन करने के लिए एक मजबूत बिंदु यह है कि जावा अंतिम स्थैतिक सदस्यों को यहां अनुमति देता है, जिनके मूल्य नहीं हो सकते हैं बाहरी वर्ग की किसी भी वस्तु से परिवर्तित। अगर मैं गलत हूं तो कृपया मुझे करने दें।


0

सबसे पहले कोई गैर-स्थिर आंतरिक वर्ग में स्थिर सदस्य को क्यों परिभाषित करना चाहता है? उत्तर है, ताकि बाहरी वर्ग का सदस्य उन स्थिर सदस्य का उपयोग केवल आंतरिक वर्ग के नाम के साथ ही कर सके?

लेकिन इस मामले के लिए हम बाहरी वर्ग में सदस्य को सीधे परिभाषित कर सकते हैं। जो बाहरी वर्ग के उदाहरण के भीतर, आंतरिक वर्ग के सभी ऑब्जेक्ट से जुड़ा होगा।

नीचे दिए गए कोड की तरह,

public class Outer {

  class Inner {

    public static void method() {

    }

  }

}

इस तरह लिखा जा सकता है

public class Outer {

  void method() {

   }

   class Inner {


  }

}

इसलिए मेरी राय में कोड जावा डिजाइनर को जटिल नहीं करना इस कार्यक्षमता की अनुमति नहीं है या हम भविष्य की रिलीज़ में कुछ और विशेषताओं के साथ इस कार्यक्षमता को देख सकते हैं।


0

कक्षा को एक सामान्य क्षेत्र के रूप में मानने की कोशिश करें, तब आप समझ पाएंगे।

//something must be static. Suppose something is an inner class, then it has static keyword which means it's a static class
Outer.something 

-1

आंतरिक वर्ग के सदस्यों को स्थैतिक होना बेकार है क्योंकि आप उन्हें पहली जगह पर नहीं ले पाएंगे।

इस बारे में सोचें, एक स्थिर सदस्य तक पहुँचने के लिए आप className.memberName का उपयोग करते हैं ,, हमारे मामले में, यह कुछ ऐसा होना चाहिए जैसे कि externalclassName.innerclassName.memberName ,,, अब आप देखते हैं कि इनरक्लैस को स्थैतिक क्यों होना चाहिए ...।


-2

आपको स्थिर नेस्टेड वर्गों पर स्थिर तरीकों की अनुमति है। उदाहरण के लिए

public class Outer {

  public static class Inner {

    public static void method() {

    }
  }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.