2009-06-22 14 views
17

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

मुझे कोई जानकारी नहीं है और इस पर विचारों की उम्मीद कर रहा था।

धन्यवाद।

+0

http://stackoverflow.com/questions/70324/java-inner-class-and-static-nested-class –

+2

"शब्दावली: नेस्टेड कक्षाएं दो श्रेणियों में विभाजित हैं: स्थैतिक और गैर स्थैतिक। नेस्टेड कक्षाएं घोषित स्थैतिक को केवल स्थैतिक घोंसले वाले वर्ग कहा जाता है। गैर स्थैतिक घोंसले वाले वर्गों को आंतरिक कक्षाएं कहा जाता है। " - http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html –

+0

संभावित डुप्लिकेट http://stackoverflow.com/questions/487126/is-usage-of-anonymous-classes से -इन-जावा-माना-खराब-शैली-या-अच्छा –

उत्तर

28

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

+1

बस डबल-ब्रेस प्रारंभकर्ताओं का उल्लेख न करें ... – skaffman

+0

बंद मूल रूप से कोड के एक स्निपेट को कहीं और भेज दिया जा सकता है, और फिर भी इसके मूल परिवेश को संदर्भित करता है। यह बहुत अच्छा हो सकता है। –

+2

@ स्काफमैन - एएके! बस उन्हें देखा, काफी विश्वास नहीं कर सका। आपको लगता है कि आपने एक सूची बनाई है? फिर से सोचो, मेरे दोस्त, फिर से अनुमान लगाओ! –

3

मुझे नहीं लगता कि वे बुरे या बुरे हैं। शायद वे व्यापक रूप से उपयोग नहीं किए जाते हैं, लेकिन उनके पास कई उपयोग हैं, कॉलबैक उनमें से एक है। एक विशेष लाभ यह है कि वे बाहरी वर्ग की तुलना में एक अलग वर्ग से विस्तार कर सकते हैं, ताकि आप एकाधिक विरासत प्राप्त कर सकें।

मैं कहूंगा कि आंतरिक कक्षाओं के साथ एक मुद्दा यह है कि उनका वाक्यविन्यास कुछ हद तक "बदसूरत" है। यह कुछ ऐसा है जो कुछ लोगों को हतोत्साहित करता है। यहां काम पर उनमें से कई हैं।

16

वे इस तरह के "खराब" नहीं हैं।

वे दुर्व्यवहार (उदाहरण के लिए, आंतरिक कक्षाओं के आंतरिक वर्ग) के अधीन हो सकते हैं। जैसे ही मेरी आंतरिक कक्षा कुछ पंक्तियों से अधिक फैलती है, मैं इसे अपनी कक्षा में निकालना पसंद करता हूं। यह कुछ मामलों में पठनीयता और परीक्षण का समर्थन करता है।

एक गॉचा है जो तुरंत स्पष्ट नहीं है, और याद रखने लायक है। किसी भी गैर- static आंतरिक वर्ग के आसपास के बाहरी वर्ग (एक अंतर्निहित 'यह' संदर्भ) का एक अंतर्निहित संदर्भ होगा। यह आम तौर पर एक मुद्दा नहीं है, लेकिन यदि आप आंतरिक कक्षा को क्रमबद्ध करने के लिए आते हैं (कहते हैं, XStream का उपयोग करके), तो आप पाएंगे कि इससे आपको अप्रत्याशित दुःख हो सकता है।

1

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

2

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

2

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

गैर स्थिर भीतरी वर्गों के साथ कुछ अन्य समस्याओं का वर्णन किया जाता है here

0

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

0

उदाहरण निम्नलिखित पर विचार करें:

public class OuterClass { 

private AnonymousInnerClass anonymousInnerClass = new AnonymousInnerClass() { 
    @Override 
    protected void printAboutme() { 
     System.out.println("AnonymousInnerClass.printAboutMe........."); 
     Class clazz = this.getClass(); 

     Field[] fields = clazz.getDeclaredFields(); 
     for (Field field : fields) { 

      String message = Modifier.isPublic(field.getModifiers()) ? "public":(Modifier.isPrivate(field.getModifiers())?"private":"protected"); 
      message = message + " " + field.getType().getSimpleName(); 
      message = message + " " + field.getName(); 

      System.out.println(message); 
     } 
    } 
}; 

public void displayAnonymousInnerClass() { 
    anonymousInnerClass.printAboutme(); 
} 

public void displayStaticInnerClass() { 
    NestedStaticClass staticInnerClass = new NestedStaticClass(); 
    staticInnerClass.printAboutMe(); 
} 

public void displayInnerClass() { 
    InnerClass innerClass = new InnerClass(); 
    innerClass.printAboutMe(); 
} 

public void displayMethodInnerClass(){ 

    class MethodInnerClass { 

     private String sampleField = "Method Inner Class"; 
     public void printAboutMe() { 
      System.out.println("MethodInnerClass.printAboutMe........."); 
      Class clazz = this.getClass(); 

      Field[] fields = clazz.getDeclaredFields(); 
      for (Field field : fields) { 

       String message = Modifier.isPublic(field.getModifiers()) ? "public":(Modifier.isPrivate(field.getModifiers())?"private":"protected"); 
       message = message + " " + field.getType().getSimpleName(); 
       message = message + " " + field.getName(); 

       System.out.println(message); 
      } 
     } 
    } 

    MethodInnerClass methodInnerClass = new MethodInnerClass(); 
    methodInnerClass.printAboutMe(); 
} 

class InnerClass { 
    private String sampleField = "Inner Class"; 
    public void printAboutMe() { 
     System.out.println("InnerClass.printAboutMe........."); 
     Class clazz = this.getClass(); 

     Field[] fields = clazz.getDeclaredFields(); 
     for (Field field : fields) { 

      String message = Modifier.isPublic(field.getModifiers()) ? "public":(Modifier.isPrivate(field.getModifiers())?"private":"protected"); 
      message = message + " " + field.getType().getSimpleName(); 
      message = message + " " + field.getName(); 

      System.out.println(message); 
     } 
    } 
} 


abstract class AnonymousInnerClass { 
    protected String sampleField = "Anonymous Inner Class"; 
    protected abstract void printAboutme(); 
} 

static class NestedStaticClass { 
    private String sampleField = "NestedStaticClass"; 
    public void printAboutMe() { 
     System.out.println("NestedStaticClass.printAboutMe........."); 
     Class clazz = this.getClass(); 

     Field[] fields = clazz.getDeclaredFields(); 
     for (Field field : fields) { 

      String message = Modifier.isPublic(field.getModifiers()) ? "public":(Modifier.isPrivate(field.getModifiers())?"private":"protected"); 
      message = message + " " + field.getType().getSimpleName(); 
      message = message + " " + field.getName(); 

      System.out.println(message); 
     } 
    } 
} 

}

इस उदाहरण में

वहाँ स्थिर नेस्टेड class.Now के साथ गैर स्थिर नेस्टेड वर्ग की हर प्रकार की तुलना है अगर आप प्रत्येक के लिए बाहरी वर्ग के प्रदर्शन विधि चलाने नेस्टेड क्लास आपको प्रत्येक नेस्टेड क्लास printAboutMe() विधि का आउटपुट दिखाई देगा, जिसमें घोंसला वाले वर्गों के सभी सदस्य चर मुद्रित करने के लिए कुछ प्रतिबिंब कोड हैं।

आप गैर नेस्टेड कक्षाओं के लिए देखेंगे कोड में घोषित चर स्ट्रिंग के अलावा एक अतिरिक्त सदस्य चर है, जो केवल रन टाइम पर मौजूद है।

उदाहरण के लिए यदि हम इनर क्लास के लिए निम्नलिखित कोड निष्पादित करते हैं। : -

public class NestedClassesDemo { 

public static void main(String[] args) { 
    OuterClass outerClass = new OuterClass(); 
    outerClass.displayInnerClass(); 
} 

}

उत्पादन इस तरह है: -

InnerClass.printAboutMe......... 
private String sampleField 
protected OuterClass this$0 

नोट है रहस्य सदस्य चर प्रकार संलग्नित क्लास (बाहरी वर्ग) के इस $ 0।

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

तो यह आंतरिक वर्गों का उपयोग खराब बनाता है अगर प्रयुक्त रूप से उपयोग नहीं किया जाता है।

स्थिर आंतरिक कक्षाओं के साथ ऐसा कोई मामला नहीं है। कृपया सभी प्रदर्शन विधियों को चलाएं। अगर कोड में कोई समस्या कृपया इंगित करें।

+1

'स्टेटिक इनर' एक [शब्दों में विरोधाभास] है (http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.1.3), और 'गैर- स्थैतिक घोंसला 'को' आंतरिक 'द्वारा प्रतिस्थापित किया जा सकता है। – EJP

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