2009-03-19 15 views
26

मुझे समझ में नहीं आता कि यह क्यों संकलित करता है। एफ() और जी() निजी होने के बावजूद, आंतरिक कक्षाओं से दिखाई दे रहे हैं। क्या वे विशेष रूप से विशेष व्यवहार करते हैं क्योंकि वे आंतरिक कक्षाएं हैं?आंतरिक कक्षाएं निजी तरीकों को सुलभ क्यों बनाती हैं?

यदि ए और बी स्थिर वर्ग नहीं हैं, तो यह अभी भी वही है।

class NotPrivate { 
    private static class A { 
     private void f() { 
      new B().g(); 
     } 
    } 

    private static class B { 
     private void g() { 
      new A().f(); 
     } 
    } 
} 

उत्तर

26

(संपादित करें: जवाब पर विस्तार कुछ टिप्पणियों को जवाब देने के लिए)

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

कुछ इस ($ लोगों संकलक द्वारा जुड़ जाते हैं) की तरह:

class A 
{ 
    private void f() 
    { 
     final B b; 

     b = new B(); 

     // call changed by the compiler 
     b.$g(); 
    } 

    // method generated by the compiler - visible by classes in the same package 
    void $f() 
    { 
     f(); 
    } 
} 

class B 
{ 
    private void g() 
    { 
     final A a; 

     a = new A(); 

     // call changed by the compiler 
     a.$f(); 
    } 

    // method generated by the compiler - visible by classes in the same package 
    void $g() 
    { 
     g(); 
    } 
} 

गैर स्थिर कक्षाओं में एक ही हैं, लेकिन वे बाहरी वर्ग के लिए एक संदर्भ के अलावा हैं, ताकि जैसे तरीकों से कर सकते हैं इसे बुलाओ

कारण जावा यह इस तरह से है कि वे आंतरिक वर्गों का समर्थन करने के वीएम परिवर्तन की आवश्यकता नहीं करना चाहता था, इसलिए सभी परिवर्तनों का संकलक स्तर पर होना ही था।

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

आप संकलक होने से बचने कर सकते हैं विधि मेरी "पैकेज" (सार्वजनिक, निजी के अभाव में, और संरक्षित) के रूप में तरीकों की घोषणा उत्पन्न करते हैं। इसका नकारात्मक पक्ष यह है कि पैकेज में कोई भी वर्ग विधियों को कॉल कर सकता है।

+1

हां, तो आप एक विधि निजी घोषित करने और संकलक यह जनता के बजाय एक त्रुटि उत्पन्न बदल जाता है? – cbrulak

+0

अच्छी तरह से यह सार्वजनिक नहीं है यह पैकेज है। और, हाँ, यही वह है जो करता है। ऐसा इसलिए है क्योंकि वीएम को आंतरिक कक्षाओं का कोई ज्ञान नहीं है ... इसलिए वीएमएल विशेष चीजों को करने के बजाय संकलक सभी काम करता है। – TofuBeer

+0

पैकेज कक्षा है जिसमें आंतरिक वर्ग शामिल है? – cbrulak

3

जावा उन में $ के साथ विशेष accessors में संकलित करता है। तो आप जावा लिख ​​नहीं सकते हैं जो निजी तरीकों तक पहुंचता है। यहां बताई गई है:

http://www.retrologic.com/innerclasses.doc7.html

वहाँ संकलक उत्पन्न सदस्यों में से एक अधिक वर्ग है। कक्षा सी का एक निजी सदस्य एम किसी अन्य कक्षा डी द्वारा उपयोग किया जा सकता है, यदि एक वर्ग दूसरे को घेरता है, या यदि वे एक सामान्य वर्ग से जुड़े होते हैं। चूंकि आभासी मशीन इस प्रकार के समूह के बारे में नहीं जानती है, इसलिए संकलक सी में पहुंच विधियों का स्थानीय प्रोटोकॉल बनाता है ताकि डी को सदस्य को पढ़ने, लिखने या कॉल करने की अनुमति मिल सके। इन तरीकों के फॉर्म के नाम $ 0 का उपयोग करते हैं, $ 1 तक पहुंचते हैं, आदि। वे कभी सार्वजनिक नहीं होते हैं। एक्सेस विधियां अनूठी हैं कि उन्हें कक्षाओं को संलग्न करने के लिए जोड़ा जा सकता है, न कि आंतरिक कक्षाओं में।

13

मुझे लगता है कि यह अच्छी तरह this quote का सार:

... इनर क्लासों की घोषणा वर्ग के सभी सदस्यों, यहां तक ​​कि निजी सदस्यों पहुँच सकते हैं। वास्तव में, आंतरिक वर्ग को कक्षा के सदस्य भी कहा जाता है; इसलिए, ऑब्जेक्ट उन्मुख इंजीनियरिंग के नियमों के पालन के बाद, इसे कक्षा के सभी सदस्यों तक पहुंच प्राप्त करनी चाहिए।

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

+0

"वास्तव में, जब आपकी वर्ग सभी आंतरिक कक्षाओं वास्तव युक्त वर्ग का हिस्सा बनने के लिए 'ढह' कर रहे हैं संकलित किया गया है की बात है।" -- इससे तुम्हारा क्या मतलब? –

+0

मुझे पूरा यकीन है कि यह सच नहीं है। आम तौर पर फॉर्म के वर्ग बाहरी $ इनर बनाए जाते हैं। आप वास्तव में ऐसा नहीं कर सकते जो आपने कहा था क्योंकि आपके भीतर आंतरिक और बाहरी वर्ग की विभिन्न संख्याएं हो सकती हैं। –

+0

आप सही हैं, यह थोड़ा भ्रामक था। मेरे जवाब से उस भाग को हटा दिया। –

0

यह specifation, यानी द्वारा काम करने की आवश्यकता है। जावा भाषा युक्ति तो कहते हैं:

6.6.1 निर्धारित पहुँच क्षमता (कम से कम JLS6 के बाद से)

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

आईई। एक निजी सदस्य का "एक्सेस-स्कोप" है: हर जगह शीर्ष-स्तरीय वर्ग निकाय की शब्दावली सीमाओं के भीतर।

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

उदाहरण के लिए एक आंतरिक वर्ग के निजी विधि बाहरी वर्ग के तरीकों से या बाहरी वर्ग का एक और भीतरी वर्ग का कोई भी तरीका से पहुँचा जा सकता।

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