2010-06-24 13 views
37

मुझे बहुत सारे जावा कोड दिखाई देते हैं जहां एंड्रॉइड डेवलपर्स को स्थिर आंतरिक कक्षाओं का उपयोग करना पसंद करता है। कस्टम ListAdapters में ViewHolder Pattern जैसे पैटर्न के लिए विशेष रूप से।एंड्रॉइड स्थिर वर्गों को पसंद क्यों करता है

मुझे यकीन नहीं है कि स्थिर और गैर स्थैतिक वर्गों के बीच मतभेद क्या हैं। मैंने इसके बारे में पढ़ा है लेकिन प्रदर्शन या स्मृति-पदचिह्न से संबंधित होने पर यह समझ में नहीं आता है।

उत्तर

62

यह न सिर्फ एंड्रॉयड डेवलपर्स है ...

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

class Outer { 
    class NonStaticInner {} 
    static class StaticInner {} 
    public List<Object> foo(){ 
     return Arrays.asList(
      new NonStaticInner(), 
      new StaticInner()); 
    } 
} 

जब आप इसे संकलन, कुछ इस तरह क्या आप प्राप्त होगा:

class Outer { 
    Outer(){} 
    public List<Object> foo(){ 
     return Arrays.asList(
      new Outer$NonStaticInner(this), 
      new StaticInner()); 
    } 
} 
class Outer$NonStaticInner { 
    private final Outer this$0; 
    Outer$NonStaticInner(Outer enclosing) { this$0 = enclosing; } 
} 
class Outer$StaticInner { 
    Outer$StaticInner(){} 
} 
+2

यह सच है, लेकिन और भी है - कभी-कभी आपके पास बाहरी वर्ग का संदर्भ नहीं होता है और फिर भी आंतरिक (यदि यह दिखाई देता है) को तुरंत चालू करना चाहता है। – ognian

+4

इंप्रेशन के लिए +1 क्या संकलक इनपुट स्रोत से बाहर निकलता है – Seven

+0

गैर-स्थैतिक आंतरिक वर्ग स्पष्ट रूप से बाह्य के संदर्भ को घोषित नहीं कर सकता है (केवल मैन्युअल रूप से इसे तुरंत चालू करने की आवश्यकता है), इस प्रकार दोनों दुनिया के सर्वश्रेष्ठ प्रदान करते हैं: स्थिर स्मृति लागत के बिना बाहरी संदर्भ? इसके अलावा, एक स्थैतिक आंतरिक वर्ग गैर-पुनर्वित्तक नहीं है, इसलिए केवल उस मामले में उपयोगी होना जहां इसके एक उदाहरण की आवश्यकता है? – samosaris

14

स्टेटिक आंतरिक कक्षाएं (यानी कक्षा static के साथ किसी अन्य वर्ग के अंदर घोषित कक्षाएं) "सामान्य" कक्षाओं के समान हैं, सिवाय इसके कि आप अपने पैकेज के नाम स्थान को प्रदूषित नहीं करते हैं। यह उनका (केवल) अंतर और लाभ है और मेरा मानना ​​है कि एंड्रॉइड में यह कारण है।

कक्षा के उद्देश्य को मुख्य वर्ग में कसने पर स्थिर आंतरिक कक्षाओं का उपयोग करें, लेकिन इसके उदाहरणों पर निर्भर नहीं है। इसे आम तौर पर एक अच्छा अभ्यास माना जाता है।

+0

क्या आप स्थैतिक आंतरिक वर्ग और आंतरिक कक्षा का गठन करने के बारे में अधिक जानकारी में जा सकते हैं? यह दिलचस्प है – Mike

24

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

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

यह स्मृति और/या प्रदर्शन को कैसे प्रभावित करता है? मैं वास्तव में नहीं जानता। :)

+2

"यह स्मृति और/या प्रदर्शन को कैसे प्रभावित करता है?" यह स्मृति रिसाव को रोक देगा। एक स्थैतिक आंतरिक वर्ग होने से गतिविधि/टुकड़े का संदर्भ बनाने से रोकता है, क्योंकि स्थैतिक आंतरिक वर्ग बाहरी सदस्य चर का उपयोग नहीं कर सकता है। अगर हमारे पास गतिविधि पर स्मृति रिसाव है, और वह गतिविधि कई भारी वस्तुओं (जैसे दृश्य) का संदर्भ रखती है, तो यह अनावश्यक स्मृति का उपभोग करेगी और प्रदर्शन को धीमा कर देगी। – aldok

4

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

स्थैतिक और गैर स्थैतिक आंतरिक कक्षाओं दोनों की दृश्यता नियंत्रित की जा सकती है। आम तौर पर वे निजी होते हैं यदि उनका कार्यान्वयन बाहरी वर्ग के आंतरिक विवरणों से दृढ़ता से जुड़ा हुआ है, और डेवलपर को नहीं लगता कि कोड का पुन: उपयोग किया जा सकता है। इस अर्थ में वे निजी कार्यों से बेहतर नहीं हैं। आंतरिक कक्षाएं Map.Entry जैसे मामलों में सार्वजनिक हो सकती हैं, जहां आंतरिक वर्ग कक्षा द्वारा उजागर इंटरफ़ेस से दृढ़ता से जुड़ा हुआ है, और डेवलपर ऐसा नहीं सोचता कि मानचित्र। एंटर्री का उपयोग किसी प्रकार के मानचित्र के बिना किया जा सकता है। दोनों प्रकार के बाहरी वर्ग के निजी सदस्यों तक पहुंच है और बाहरी वर्ग के पास आंतरिक वर्ग के निजी सदस्यों तक पहुंच है।

स्थैतिक और गैर स्थैतिक आंतरिक कक्षाओं के उदाहरण कचरे को हर दूसरे वर्ग की तरह एकत्रित किया जाता है।बाहरी वर्ग के हथियार संग्रह और आंतरिक वर्ग के कचरे के संग्रह के बीच कोई विशेष संबंध नहीं है।

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

4

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

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

class Outer{ 
    class Inner{//Only works with non static inner class 
      public Outer getOuter(){return Outer.this;} 
    } 
} 

यह भी इसके उपयोग के लिए प्रासंगिक है, बाहरी वर्ग के संदर्भ में आंतरिक वर्ग के एक ctor तर्क, एक नया गैर स्थिर आंतरिक वर्ग वस्तु आप एक पर एक memberfunction तरह ctor कॉल करनी होगी बनाने के लिए है बाहरी वर्ग का उदाहरण या बाहरी वर्ग के सदस्य के भीतर से। इसका मतलब है कि बाहरी कक्षा के उदाहरण के बिना आप आंतरिक कक्षा का उदाहरण नहीं ले सकते हैं।

Outer.Inner in = new Outer().new Inner(); 
संबंधित मुद्दे