2009-12-04 16 views
28

इन दो आंतरिक क्लास घोषणाओं के बीच क्या अंतर है? फायदे/नुकसान पर भी टिप्पणी करें?इंटरफेस बनाम कक्षा में

केस ए: कक्षा के भीतर कक्षा।

public class Levels { 
    static public class Items { 
    public String value; 
    public String path; 

    public String getValue() { 
     return value;} 
    } 
} 

और केस बी: इंटरफ़ेस के भीतर कक्षा।

public interface Levels{ 

    public class Items { 
    public String value; 
    public String path; 

    public String getValue() { 
     return value;} 
    } 
} 

मेड सुधार: Getvalue विधि के प्लेसमेंट के लिए।

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

public class Z{//NOTE: NO INTERFACE IMPLEMENTED here!!!! 
Levels.Items items = new Levels.Items(); 
} 

के बाद से एक अंतरफलक instantiated नहीं है, एक अंतरफलक के अंदर सभी तत्वों स्तर instantiated बस क्योंकि आप एक इंटरफेस का दृष्टांत नहीं कर सकते हैं इंटरफ़ेस के बिना डॉट नोटेशन से सुलभ हैं।

तो यह कहकर कि बी वर्ग के मामले में आइटम वर्ग स्थिर नहीं है। चूंकि दोनों मामलों में ए और बी को तत्काल तत्काल किया जाता है, इसलिए मैं स्थैतिक या आंतरिक या घोंसले पर अर्थशास्त्र की तलाश नहीं कर रहा हूं। मुझे अर्थशास्त्र पर जवाब देना बंद करो। मैं संकलक, रनटाइम और व्यवहार संबंधी मतभेद/फायदे चाहता हूं, या यदि कोई ऐसा नहीं कहता है। अर्थशास्त्र पर कोई और जवाब कृपया !!!!! जेवीएम या .NET वीएम विनिर्देशन पर एक विशेषज्ञ पाठ पुस्तक अर्थात् पुजारी के बजाय इस उत्तर प्रश्न को खुश करें।

+0

साक्षात्कार का उत्पादन सवाल? –

+0

मैं अर्थशास्त्र की तलाश नहीं कर रहा हूं कि इसे आंतरिक या घोंसला वर्ग कहा जाता है या नहीं। मैं फीचर मतभेदों की तलाश में हूं। –

+2

@ h2g2 - केवल कोड को दोबारा सुधारने के बाद - आप दूसरा उदाहरण गलत है, आपके पास इंटरफेस में एक कार्यान्वित विधि नहीं हो सकती है। या शायद घुंघराले ब्रैकेट उनके सही स्थानों पर नहीं थे ... –

उत्तर

14

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

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

Levels levels = new Levels(); // first need an instance of the enclosing class 

// The items object contains an implicit reference to the levels object 
Levels.Items items = levels.new Items(); 

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

एक गैर स्थैतिक आंतरिक वर्ग घोषित करना एक आम गलती है जब आपको केवल स्थिर आंतरिक वर्ग व्यवहार की आवश्यकता होती है।

+1

गैर स्थैतिक आंतरिक कक्षाएं काफी आम हैं, खासकर ग्राफिक्स कोड – gerardw

27

एक static आंतरिक वर्ग एक घोंसला वर्ग है, और गैर स्थैतिक को आंतरिक कक्षा कहा जाता है। अधिक के लिए, look here

हालांकि, मैं एक ही लिंक से एक उद्धरण उद्धृत करना चाहता हूं।

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

आपने दूसरे मामले में static शब्द का उपयोग नहीं किया। और आपको लगता है कि यह निश्चित रूप से static होगा क्योंकि यह एक इंटरफ़ेस है। आप इसे मानने में सही हैं।

आप एक स्थिर नेस्टेड क्लास की तरह, अपने इंटरफ़ेस में भीतरी कक्षा को तुरंत चालू कर सकते हैं, क्योंकि यह वास्तव में static नेस्टेड क्लास है।

Levels.Items hello = new Levels.Items(); 

तो, ऊपर बयान अपने मामलों दोनों में मान्य होगा। आपका पहला मामला स्थिर नेस्टेड क्लास का है, और दूसरे मामले में आपने static निर्दिष्ट नहीं किया है, लेकिन फिर भी यह एक स्थिर नेस्टेड क्लास होगा क्योंकि यह इंटरफ़ेस में है। इसलिए, इस तथ्य के अलावा कोई फर्क नहीं पड़ता कि एक वर्ग में घोंसला है, और दूसरा इंटरफ़ेस में है।

आम तौर पर कक्षा में एक आंतरिक वर्ग, इंटरफ़ेस में नहीं, नीचे की तरह तत्काल किया जाएगा।

Levels levels = new Levels(); 
Levels.Items items = levels.new Items(); 

इसके अलावा, एक "गैर स्थिर" आंतरिक वर्ग इसकी बाहरी वर्ग के लिए एक अंतर्निहित संदर्भ होगा। यह "स्थैतिक" नेस्टेड वर्ग के मामले में नहीं है।

+0

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

+0

मेरा परिशिष्ट देखें। –

0

आईएमएचओ, लाभ यह है कि यदि आप छोटे होते हैं तो आपको अपने प्रोजेक्ट फ़ोल्डर को कम करने वाले कम वर्ग मिलते हैं; नुकसान यह है कि जब आपकी आंतरिक कक्षा आवश्यकता परिवर्तन के साथ बढ़ती जा रही है, तो maintainenacne आपका दुःस्वप्न बन गया।

0

मैंने सोचा कि पहला व्यक्ति कक्षा स्तर और एक स्थिर आंतरिक वर्ग घोषित करता है जिसे आइटम कहा जाता है। वस्तुओं को स्तरों द्वारा संदर्भित किया जा सकता है। यह लगता है और स्थिर होगा।

दूसरा एक सरल भीतरी वर्ग है, जो Levels.Items उपयोग करते हुए, निम्नलिखित में की तरह द्वारा पहुँचा जा सकता घोषणा करेंगे जबकि:

Levels.Items hello = new Levels.Items(); 

संपादित करें: इस पूरी तरह से गलत है, टिप्पणियां और अन्य उत्तर पढ़ें।

+1

आपका पहला अनुच्छेद कुल गलतफहमी है। इस मामले में 'स्थिर' शब्द से भ्रमित न हों। –

+1

इसके अलावा, आपका कोड स्निपेट 'स्थिर 'नेस्टेड क्लास के लिए पूरी तरह मान्य है। लेकिन आंतरिक कक्षा के लिए नहीं। इसलिए, आपका कोड आपके द्वारा डाले गए संदर्भ में अमान्य हो जाता है। यह कुछ स्तर जैसा होना चाहिए। आइटम आइटम = स्तरInstance.new आइटम(); '। ध्यान दें, आप बाहरी को तत्काल बिना किसी भीतरी कक्षा को तुरंत चालू नहीं कर सकते हैं। मुझे आशा है कि यह संदेह को साफ़ करेगा। –

+0

मुझे सुधारने के लिए धन्यवाद। – BlueTrin

7

आपके द्वारा घोंसले/आंतरिक कक्षाओं के उदाहरण उदाहरण हैं (आईएमओ) खराब उदाहरण हैं। दूसरे उदाहरण के अलावा वैध जावा नहीं है क्योंकि एक इंटरफेस केवल सार (विधियों) घोषित कर सकता है।

public interface Worker { 

    public class Response { 
     private final Status status; 
     private final String message; 
     public Response(Status status, String message) { 
      this.status = status; this.message = message; 
     } 
     public Status getStatus() { return status; } 
     public String getMessage() { return message; } 
    } 

    ... 

    public Response doSomeOperation(...); 
} 

रिस्पांस वर्ग को एम्बेड करके हम संकेत कर रहे हैं कि यह कोई अन्य उपयोगों के साथ कार्यकर्ता एपीआई का एक मूलभूत हिस्सा है: यहाँ एक बेहतर उदाहरण है।

मानचित्र। एंटर्री क्लास इस मुहावरे का एक प्रसिद्ध उदाहरण है।

+1

['Map.Entry'] (https://docs.oracle.com/javase/8/docs/api/java/util/Map.Entry.html) एक इंटरफ़ेस है। –

15

आप एक इंटरफेस में एक नेस्टेड वर्ग घोषित, तो यह हमेशा सार्वजनिक और स्थिर है।तो:

public interface Levels{ 
    class Items { 
     public String value; 
     public String path; 

     public String getValue() {return value;} 
    } 
} 

बिल्कुल के रूप में

public interface Levels{ 
    public static class Items { 
     public String value; 
     public String path; 

     public String getValue() {return value;} 
    } 
} 

और यहां तक ​​कि

public interface Levels{ 
    static class Items { 
     public String value; 
     public String path; 

     public String getValue() {return value;} 
    } 
} 

एक ही है मैं javap -verbose के साथ इस जाँच लिया है और वे सभी

Compiled from "Levels.java" 
public class Levels$Items extends java.lang.Object 
    SourceFile: "Levels.java" 
    InnerClass: 
    publiC#14= #3 of #23; //Items=class Levels$Items of class Levels 
    minor version: 0 
    major version: 50 
    Constant pool: 
const #1 = Method #4.#21; // java/lang/Object."<init>":()V 
const #2 = Field #3.#22; // Levels$Items.value:Ljava/lang/String; 
const #3 = class #24; // Levels$Items 
const #4 = class #25; // java/lang/Object 
const #5 = Asciz value; 
const #6 = Asciz Ljava/lang/String;; 
const #7 = Asciz path; 
const #8 = Asciz <init>; 
const #9 = Asciz ()V; 
const #10 = Asciz Code; 
const #11 = Asciz LineNumberTable; 
const #12 = Asciz LocalVariableTable; 
const #13 = Asciz this; 
const #14 = Asciz Items; 
const #15 = Asciz InnerClasses; 
const #16 = Asciz LLevels$Items;; 
const #17 = Asciz getValue; 
const #18 = Asciz ()Ljava/lang/String;; 
const #19 = Asciz SourceFile; 
const #20 = Asciz Levels.java; 
const #21 = NameAndType #8:#9;// "<init>":()V 
const #22 = NameAndType #5:#6;// value:Ljava/lang/String; 
const #23 = class #26; // Levels 
const #24 = Asciz Levels$Items; 
const #25 = Asciz java/lang/Object; 
const #26 = Asciz Levels; 

{ 
public java.lang.String value; 

public java.lang.String path; 

public Levels$Items(); 
    Code: 
    Stack=1, Locals=1, Args_size=1 
    0: aload_0 
    1: invokespecial #1; //Method java/lang/Object."<init>":()V 
    4: return 
    LineNumberTable: 
    line 2: 0 

    LocalVariableTable: 
    Start Length Slot Name Signature 
    0  5  0 this  LLevels$Items; 


public java.lang.String getValue(); 
    Code: 
    Stack=1, Locals=1, Args_size=1 
    0: aload_0 
    1: getfield #2; //Field value:Ljava/lang/String; 
    4: areturn 
    LineNumberTable: 
    line 7: 0 

    LocalVariableTable: 
    Start Length Slot Name Signature 
    0  5  0 this  LLevels$Items; 


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