2009-07-06 8 views
10

निम्नलिखित मामले पर विचार करें:जावा भीतरी वर्ग दृश्यता पहेली

public class A { 
    public A() { b = new B(); } 
    B b; 
    private class B { } 
} 

ग्रहण में एक चेतावनी से मुझे लगता है कि बोली: जावा संकलक निर्माता a.b() एक कृत्रिम एक्सेसर विधि द्वारा emulates। मुझे लगता है कि कंपाइलर अब आगे बढ़ता है और बी

मुझे लगता है कि यह अजीब बात है: क्लास बी को .k.o. के रूप में क्यों दिखाई नहीं देगा। ए में क्षेत्र? और: क्या इसका मतलब यह है कि कक्षा बी अब रन समय पर निजी नहीं है? और: कक्षा बी के लिए सुरक्षित कीवर्ड क्यों व्यवहार करता है?

public class A { 
    public A() { b = new B(); } 
    B b; 
    protected class B { } 
} 

उत्तर

24

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

जब आप बी को संरक्षित कन्स्ट्रक्टर देते हैं, तो ए उस कन्स्ट्रक्टर तक पहुंच सकता है क्योंकि यह एक ही पैकेज में है, बिना सिंथेटिक कन्स्ट्रक्टर को जोड़ने के लिए।

+0

ठीक है, मैं इसे देखता हूं। मेरे लिए इसका मतलब है कि मैं उदाहरण के समान आंतरिक वर्गों के उपयोग से बचूंगा, यह केवल भ्रम पैदा कर सकता है। – Gerard

+2

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

+0

सिंथेटिक विधियों IMHO भाषा के लिए एक अनावश्यक अतिरिक्त थे। बस "निजी" सदस्यों (जो संकलक हुड के नीचे करता है) के लिए पैकेज स्कोप का उपयोग करना एक संतोषजनक समाधान था। – finnw

-1

आप

this.new B(); 
+0

क्षमा करें, लेकिन यह। नया बी(); एक ही चेतावनी और व्यवहार देता है। – Gerard

+2

@ रैट्स: इससे हाथ में समस्या में कोई फर्क नहीं पड़ता। "यह" योग्यता निहित है। – skaffman

2

class B और इसकी कन्स्ट्रक्टर की पहुंच समान नहीं है। आपके पास पैकेज-स्कोप कन्स्ट्रक्टर के साथ एक निजी आंतरिक कक्षा हो सकती है, और यही वह है जो मैं आमतौर पर करता हूं।

public class A { 
    public A() { b = new B(); } 
    B b; 
    private class B { 
    B() { } 
    } 
} 
+0

लेकिन आपके पास एक उचित निजी वर्ग का पैकेज-निजी उदाहरण कैसा हो सकता है? – einpoklum

4

मैं जानता हूँ कि इस सवाल का अब लगभग तीन साल पुराना है, लेकिन मुझे लगता है कि सवाल का एक हिस्सा अभी भी उत्तर नहीं मिलता है:

और: इसका मतलब यह है कि वर्ग बी है नहीं रह गया है निजी चलने के समय पर?

कार्लोस Heubergers skaffmans जवाब पर टिप्पणी पता चलता है, वर्ग B अभी भी private पैकेज में अन्य वर्गों के लिए है।

वह शायद जावा प्रोग्रामिंग भाषा के लिए सही है, यानी किसी अन्य वर्ग से कक्षा B को संदर्भित करना संभव नहीं है। प्रतिबिंब का उपयोग किए बिना कम से कम नहीं (जिसके साथ निजी वर्ग के सदस्यों को बाहर से भी पहुंचा जा सकता है), लेकिन यह एक और मुद्दा है।

लेकिन जैसा कि JVM में एक आंतरिक वर्ग (स्काफमैन राज्यों के रूप में) की कोई अवधारणा नहीं है, मैंने खुद से पूछा कि कैसे "केवल एक वर्ग द्वारा सुलभ" दृश्यता बाइटकोड स्तर पर महसूस की जाती है। उत्तर: यह बिल्कुल एहसास नहीं हुआ है, जेवीएम के लिए आंतरिक वर्ग सामान्य पैकेज निजी वर्ग की तरह दिखता है। यह है, अगर आप अपने लिए बाइटकोड लिखते हैं (या कंपाइलर द्वारा जेनरेट किए गए एक को संशोधित करते हैं) तो आप समस्याओं के बिना कक्षा B तक पहुंच सकते हैं।

आप उसी पैकेज में सभी कक्षाओं के सभी सिंथेटिक एक्सेसर विधियों तक भी पहुंच सकते हैं। इसलिए यदि आप की विधि में कक्षा A के किसी निजी क्षेत्र में मान निर्दिष्ट करते हैं, तो डिफ़ॉल्ट रूप से एक सिंथेटिक एक्सेसर विधि (यानी पैकेज निजी) दृश्यता A (access$000 जैसी कुछ नाम) में उत्पन्न होती है जो आपके लिए मान निर्धारित करती है। इस विधि को केवल कक्षा B से बुलाया जाना चाहिए (और वास्तव में इसे केवल जावा भाषा का उपयोग करके ही कहा जा सकता है)।लेकिन जेवीएम के दृष्टिकोण से, यह किसी अन्य के रूप में सिर्फ एक विधि है और इसे किसी भी वर्ग द्वारा बुलाया जा सकता है।

तो, सवाल का जवाब देने:

  • देखने के जावा भाषा की दृष्टि से, वर्ग B है और निजी रहता है।
  • जेवीएम के दृष्टिकोण से, कक्षा B (या बेहतर: कक्षा A$B) निजी नहीं है।
+0

सही है, लेकिन यह वही नहीं है जो मैंने सुझाया था। मैंने लिखा "** सदस्य ** अभी भी निजी हैं" - मेरा मतलब वर्ग के क्षेत्र था और ** कक्षा ** ** आपके द्वारा व्याख्या की गई नहीं है! यह प्रश्न [टैग: जावा] के बारे में है और नहीं [टैग: बाइटकोड] (पीढ़ी, संशोधन, _hacking_ ...)। –

+0

@ कार्लोस हेबेगर निश्चित रूप से यह आपके लिए कोई अपराध नहीं था! निश्चित रूप से कक्षा बी के सदस्य अभी भी निजी हैं, लेकिन कक्षा बी (वर्ग ए के सदस्य के रूप में) नहीं है (जेवीएम के दृष्टिकोण से), और यह जेरार्ड द्वारा मूल प्रश्न था। और हाँ, सवाल जावा के बारे में है, लेकिन टैग विकी में बताया गया है: "जावा एक प्रोग्रामिंग भाषा है और ** रनटाइम पर्यावरण **" है। और रनटाइम पर्यावरण JVM है और JVM प्रति से जावा प्रोग्रामिंग भाषा से कोई लेना देना नहीं है लेकिन केवल बाइटकोड का अर्थ है। – siegi

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