बाहरी जावा वर्ग आंतरिक वर्ग के निजी सदस्यों तक क्यों पहुंच सकते हैं?


177

मैंने देखा कि बाहरी कक्षाएं निजी वर्गों के आंतरिक उदाहरण चर तक पहुंच सकती हैं। यह कैसे हो सकता है? यहाँ एक नमूना कोड प्रदर्शित किया गया है:

class ABC{
    class XYZ{
        private int x=10;
    }

    public static void main(String... args){
        ABC.XYZ xx = new ABC().new XYZ();
        System.out.println("Hello :: "+xx.x); ///Why is this allowed??
    }
}

इस व्यवहार की अनुमति क्यों है?


इस सवाल ने मुझे काफी देर तक भ्रमित किया जब तक कि मुझे टिप्पणी नहीं दिखाई दी ... जो बताता है कि मैं अपनी मशीन पर xx.x का उपयोग क्यों नहीं कर सकता ..
वांग शेंग

4
टिप्पणियों ने मुझे भ्रमित किया, मैं जावा 8 में उपरोक्त कोड चलाता हूं, यह संकलन और चलाता है। xx.x तक पहुँचा जा सकता है।
लियोन

हरीश, क्या आप स्वीकार किए गए उत्तर को अन-एक्सेप्ट कर सकते हैं (जो आपके द्वारा पूछे गए प्रश्न का उत्तर नहीं देता है) और इसके बजाय नीचे दिए गए मार्टिन एंडरसन के उत्तर को स्वीकार करें, जो बहुत अच्छी तरह से इसका उत्तर देता है?
temporary_user_name

एफडब्ल्यूआईडब्ल्यू यह वाक्यविन्यास बिल्कुल भयावह है:new ABC().new XYZ()
जोश एम।

जवाबों:


80

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

  1. आपके बाहरी वर्ग में कार्यक्षमता का कुछ टुकड़ा सबसे स्पष्ट होगा यदि इसे एक अलग वर्ग में लागू किया गया था।
  2. भले ही यह एक अलग वर्ग में है, लेकिन कार्यक्षमता बहुत बारीकी से इस तरह से बंधी हुई है कि बाहरी वर्ग काम करता है।

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


217
यह उत्तर बताता है कि क्यों नेस्टेड कक्षाओं में उनके बाहरी वर्ग के निजी सदस्यों तक पहुंच है। लेकिन सवाल यह है कि बाहरी वर्ग के पास नेस्टेड वर्गों के निजी सदस्यों तक पहुंच क्यों है।
एंड्रयू

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

13
यह इस समस्या का सही उत्तर नहीं है, यहाँ है: stackoverflow.com/questions/19747812/…
कॉलिन सु

4
@anthropomo: नहीं, ऐसा नहीं है। बाहरी वर्ग के निजी सदस्यों के लिए किसी भी पहुंच वाले बाहरी वर्ग के बिना दोनों आवश्यकताएं पूरी तरह से संभव हैं।
या मैपर

एक अच्छा उदाहरण जहां यह विशेष रूप से उपयोगी है बिल्डर पैटर्न, stackoverflow.com/a/1953567/1262000 । पैरेंट क्लास को बस एक कंस्ट्रक्टर की ज़रूरत होती है जो एक बिल्डर को लेता है और अपने सभी सदस्य चर को एक्सेस करता है। अन्यथा आपको सभी निजी सदस्य चर के साथ मूल श्रेणी में एक निजी निर्माणकर्ता की आवश्यकता होगी।
vikky.rk

62

यदि आप अपने आंतरिक वर्ग के निजी सदस्यों को छिपाना पसंद करते हैं, तो आप सार्वजनिक सदस्यों के साथ एक इंटरफ़ेस परिभाषित कर सकते हैं और एक अनाम आंतरिक वर्ग बना सकते हैं जो इस इंटरफ़ेस को लागू करता है। उदाहरण bellow:

class ABC{
    private interface MyInterface{
         void printInt();
    }

    private static MyInterface mMember = new MyInterface(){
        private int x=10;

        public void printInt(){
            System.out.println(String.valueOf(x));
        }
    };

    public static void main(String... args){
        System.out.println("Hello :: "+mMember.x); ///not allowed
        mMember.printInt(); // allowed
    }
}

यह कोड का एक शानदार स्निपेट है। मुझे जिस चीज की जरूरत थी। धन्यवाद!
केविनरपे

कृपया वह कोड प्रदान करें जो चलाने में सक्षम हो। निजी चर का उपयोग करने की अनुमति नहीं दी जा सकती है, इसके कारण क्या है।
androidyue

7
लेकिन फिर ... भीतर का वर्ग गुमनाम है। आप उस आंतरिक वर्ग के कई उदाहरण नहीं बना सकते हैं, या किसी भी चर घोषणाओं आदि के लिए उस आंतरिक वर्ग का उपयोग नहीं कर सकते हैं
या मैपर

@OR मैपर इसीलिए भले ही यहां xसार्वजनिक हो, लेकिन इसकी अनुमति नहीं है mMember.x
मैक

54

आंतरिक वर्ग (अभिगम नियंत्रण के प्रयोजनों के लिए) युक्त वर्ग का हिस्सा माना जाता है। इसका मतलब सभी निजी लोगों तक पूरी पहुंच है।

इसे लागू करने का तरीका सिंथेटिक पैकेज-संरक्षित विधियों का उपयोग कर रहा है: आंतरिक वर्ग को एक ही पैकेज (एबीसी $ XYZ) में एक अलग वर्ग के लिए संकलित किया जाएगा। JVM सीधे अलगाव के इस स्तर का समर्थन नहीं करता है, जिससे कि bytecode-level ABC $ XYZ में पैकेज-संरक्षित विधियाँ होंगी जो बाहरी वर्ग निजी विधियों / क्षेत्रों में जाने के लिए उपयोग करता है।


17

इसी तरह के एक और सवाल पर एक सही जवाब दिखाई दे रहा है: एक नेस्टेड क्लास के निजी सदस्य को एनक्लोजिंग क्लास के तरीकों से क्यों एक्सेस किया जा सकता है?

इसमें कहा गया है कि JLS पर निजी स्कूपिंग की परिभाषा है - अभिगम्यता का निर्धारण :

अन्यथा, यदि सदस्य या कंस्ट्रक्टर को निजी घोषित किया जाता है, तो पहुँच की अनुमति दी जाती है, यदि केवल और अगर यह शीर्ष स्तर वर्ग (class7.6) के निकाय के भीतर होता है, जो सदस्य या कंस्ट्रक्टर की घोषणा को संलग्न करता है।


मुझे लगता है कि इस स्निपेट से मेरे सवाल का जवाब मिल सकता है।
शेन

5

आंतरिक वर्गों के लिए एक IMHO महत्वपूर्ण उपयोग का मामला कारखाना पैटर्न है। संलग्नक वर्ग आंतरिक वर्ग w / o पहुंच प्रतिबंधों का एक उदाहरण तैयार कर सकता है और उस उदाहरण को बाहरी दुनिया में पारित कर सकता है, जहां निजी पहुंच को सम्मानित किया जाएगा।

वर्ग स्थिर घोषित करने के लिए विरोधाभास में संलग्नक वर्ग में प्रवेश प्रतिबंधों को नहीं बदलता है, जैसा कि नीचे दिखाया गया है। इसके अलावा एक ही संलग्न वर्ग में स्थिर वर्गों के बीच पहुँच प्रतिबंध काम कर रहे हैं। मैं हैरान था ...

class MyPrivates {
    static class Inner1 { private int test1 = 2; }
    static class Inner2 { private int test2 = new Inner1().test1; }

    public static void main(String[] args) {
        System.out.println("Inner : "+new Inner2().test2);
    }
}

1
अच्छी टिप्पणी लेकिन कोई जवाब नहीं।
8

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

3

एक्सेस प्रतिबंध प्रति वर्ग आधार पर किया जाता है। उदाहरण / वर्ग के सभी सदस्यों तक पहुँचने में सक्षम नहीं होने के लिए एक कक्षा में घोषित विधि के लिए कोई रास्ता नहीं है। इसका कारण यह है कि आंतरिक कक्षाओं में बाहरी वर्ग के सदस्यों के लिए भी अनपेक्षित पहुंच होती है, और बाहरी वर्ग की आंतरिक कक्षा के सदस्यों तक पहुंच नहीं होती है।

एक वर्ग को दूसरे वर्ग के अंदर रखकर आप इसे लागू करने के लिए कसकर बांध रहे हैं, और जो कुछ भी कार्यान्वयन का हिस्सा है, उसे अन्य भागों तक पहुंच होना चाहिए।


3

आंतरिक कक्षाओं के पीछे तर्क यह है कि यदि आप एक बाहरी वर्ग में एक आंतरिक वर्ग बनाते हैं, तो ऐसा इसलिए है क्योंकि उन्हें कुछ चीजें साझा करने की आवश्यकता होगी, और इस प्रकार यह समझ में आता है कि उनके लिए "नियमित" कक्षाओं की तुलना में अधिक लचीलापन होना चाहिए।

यदि, आपके मामले में, यह वर्गों के लिए कोई मतलब नहीं है कि वे एक-दूसरे के आंतरिक कामकाज को देखने में सक्षम हो सकते हैं - जिसका मूल रूप से मतलब है कि आंतरिक वर्ग को केवल एक नियमित वर्ग बनाया जा सकता है, तो आप भीतर के वर्ग को घोषित कर सकते हैं static class XYZ। उपयोग करने staticका मतलब है कि वे राज्य को साझा नहीं करेंगे (और, उदाहरण के लिए new ABC().new XYZ()काम नहीं करेंगे, और आपको उपयोग करने की आवश्यकता होगी new ABC.XYZ()
लेकिन, अगर ऐसा है, तो आपको इस बारे में सोचना चाहिए कि क्या XYZवास्तव में एक आंतरिक वर्ग होना चाहिए और शायद यह अपना खुद का हकदार है। फ़ाइल। कभी-कभी यह एक स्थिर आंतरिक वर्ग बनाने के लिए समझ में आता है (उदाहरण के लिए, यदि आपको एक छोटे वर्ग की ज़रूरत है जो आपके बाहरी वर्ग का उपयोग करने वाले इंटरफ़ेस को लागू करता है, और जो कहीं और सहायक नहीं होगा) लेकिन लगभग आधे समय में। इसे एक बाहरी वर्ग बनाया जाना चाहिए था।


2
बाहरी वर्ग स्थिर आंतरिक वर्गों के निजी सदस्यों को भी एक्सेस कर सकता है , इसलिए इसका स्थैतिक से कोई लेना-देना नहीं है । आप कहते हैं कि "इससे कोई मतलब नहीं है कि कक्षाएं एक-दूसरे के आंतरिक कामकाज को देखने में सक्षम हैं", लेकिन यह जरूरी नहीं है कि क्या होगा - अगर यह बाहरी वर्ग के आंतरिक कामकाज को देखने के लिए सिर्फ आंतरिक वर्ग के लिए समझ में आता है, लेकिन नहीं- विपरीत?
या मैपर

3

थिलो ने आपके पहले प्रश्न "यह कैसे संभव है?" के लिए एक अच्छा उत्तर जोड़ा । मैं दूसरे पूछे गए प्रश्न पर थोड़ा विस्तार करना चाहता हूं: इस व्यवहार की अनुमति क्यों है?

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

तो, फिर क्यों? मुझे लगता है कि एक उदाहरण बिंदु को बेहतर बताता है।

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

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

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


1
यह वास्तविक रूप से स्वीकृत उत्तर होना चाहिए। इतना स्पष्ट और संपूर्ण। इसके बजाय स्वीकार किए गए जवाब भी सवाल का जवाब नहीं है।
temporary_user_name

IMO अभी भी इस सवाल का जवाब नहीं देता है कि हम आसानी से निजी क्षेत्रों को एक आंतरिक वर्ग में नहीं जोड़ सकते हैं, जो बाहरी वर्ग सीधे पहुंच नहीं सकता है। जब तक मैं गलत नहीं हूँ, यह आंतरिक वर्गों के लिए प्राथमिक मामलों में से एक को बर्बाद कर देता है - अल्पकालिक "संरचना जैसी", अपरिवर्तनीय प्रकार। FWIW C # खुशी से इसका समर्थन करता है: repl.it/repls/VengefulCheeryInverse
जोश एम।

-1

आंतरिक वर्ग को बाहरी वर्ग की विशेषता के रूप में माना जाता है। इसलिए, कोई फर्क नहीं पड़ता कि इनर क्लास इंस्टेंस वैरिएबल निजी है या नहीं, आउटर क्लास बिना किसी समस्या के एक्सेस कर सकता है, जैसे कि इसके अन्य प्राइवेट फीचर्स (वैरिएबल) एक्सेस करना।

class Outer{

private int a;

class Inner{
private int b=0;
}

void outMethod(){
a = new Inner().b;
}
}

-2

क्योंकि आपकी main()पद्धति ABCकक्षा में है, जो अपने स्वयं के आंतरिक वर्ग तक पहुंच सकती है


2
सवाल यह नहीं है कि क्या ABCकक्षा के सदस्य कक्षा में नेस्टेड कक्षाओं तक पहुँच प्राप्त कर सकते हैं ABC, लेकिन वे जावा में कक्षा में निहित कक्षाओं के निजी सदस्यों तक क्यों पहुँच सकते हैं ABC
या मैपर

मैंने उसी दिन इस सवाल का जवाब दिया था। किसी ने 2 साल बाद प्रश्न संपादित किया, और 3 साल बाद नीचे आया। मुझे पूरा यकीन है कि जिसने भी प्रश्न संपादित किया है उसने प्रश्न के शब्दांकन को पूरी तरह से बदल दिया है।
aberrant80
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.