जावा में एक स्थिर नेस्टेड इंटरफ़ेस का उपयोग क्यों किया जाएगा?


235

मुझे अभी हमारे कोड-बेस में एक स्थिर नेस्टेड इंटरफ़ेस मिला है।

class Foo {
    public static interface Bar {
        /* snip */
    }
    /* snip */
}

मैंने पहले इसे कभी नहीं देखा है। मूल डेवलपर पहुंच से बाहर है। इसलिए मुझे SO से पूछना है:

स्थैतिक इंटरफ़ेस के पीछे शब्दार्थ क्या हैं? अगर मैं निकाल दूं तो क्या होगा static? कोई यह क्यूँ करेगा?


2
यह एक 'आंतरिक इंटरफ़ेस नहीं है: यह एक नेस्टेड इंटरफ़ेस है। जावा में इनर का एक विशिष्ट अर्थ है।
लोर्ने की

जवाबों:


293

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

किसी भी तरह से, डेवलपर केवल Foo.Bar नाम का एक इंटरफ़ेस घोषित कर रहा है। एनक्लोजिंग क्लास के साथ कोई और जुड़ाव नहीं है, सिवाय इसके कि कोड जो फू का उपयोग नहीं कर सकता है वह फू को भी एक्सेस नहीं कर पाएगा। (स्रोत कोड से - बाइटकोड या प्रतिबिंब Foo.Bar तक पहुंच सकता है, भले ही फू पैकेज-निजी हो!)

इस तरह से नेस्टेड इंटरफ़ेस बनाने के लिए यह स्वीकार्य शैली है यदि आप इसे केवल बाहरी वर्ग से उपयोग करने की अपेक्षा करते हैं, ताकि आप एक नया शीर्ष-स्तरीय नाम न बनाएँ। उदाहरण के लिए:

public class Foo {
    public interface Bar {
        void callback();
    }
    public static void registerCallback(Bar bar) {...}
}
// ...elsewhere...
Foo.registerCallback(new Foo.Bar() {
    public void callback() {...}
});

1
जेसी ग्लिक के उत्तर में, इसका क्या अर्थ है: (स्रोत कोड से - बायटेकोड या प्रतिबिंब Foo.Bar तक पहुंच सकता है, भले ही फू पैकेज-निजी हो!)।
वासु

कैलाश, निजी तरीकों को रिलेफेक्शन (रिफ्लेक्ट पैकेज में) के माध्यम से और सीधे उत्पन्न .class फ़ाइलों के बायटेक तक पहुँचने के माध्यम से पहुँचा जा सकता है।
गमोर

2
"Bytecode ... द्वारा Foo.Bar का उपयोग कर सकते हैं" मेरा मतलब है कि Foo.Bar को संदर्भित करने वाला एक संकलित वर्ग लोड किया जा सकता है और भले ही वह फू का संदर्भ न दे सके। ऐसा तब हो सकता है यदि Foo के सार्वजनिक होने पर, या किसी गैर-जावा भाषा आदि से कक्षा को हाथ से इकट्ठा या संकलित किए जाने पर, क्लास को संकलित किया गया था। जावा कंपाइलर, हालांकि, एन्क्लेव क्लास पर पहुंच संशोधक की जांच करता है यहां तक ​​कि जब परिणामी बाइटकोड उस संलग्न वर्ग का संदर्भ नहीं देगा।
जेसी ग्लिक

@ जेसे क्या निजी शीर्ष स्तर के निजी स्थिर वर्ग को प्रतिबिंब के माध्यम से प्रवेश किया जा सकता है?
पचेरियर

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

72

इस सवाल का जवाब दिया गया है, लेकिन एक नेस्टेड इंटरफ़ेस का उपयोग करने का एक अच्छा कारण यह है कि यदि इसका कार्य सीधे उस कक्षा से संबंधित है जो इसका एक अच्छा उदाहरण है Listener। यदि आपके पास एक वर्ग था Fooऔर आप चाहते थे कि अन्य कक्षाएं उस पर होने वाली घटनाओं को सुनने में सक्षम हों, तो आप एक इंटरफ़ेस घोषित कर सकते हैं FooListener, जो कि ठीक है, लेकिन संभवतः एक नेस्टेड इंटरफ़ेस की घोषणा करना और उन अन्य वर्गों को लागू करना अधिक स्पष्ट होगा Foo.Listener( एक नेस्टेड क्लास Foo.Eventइसके साथ बुरा नहीं है)।


11
एक विशिष्ट उदाहरण है java.util.Map.Entry(जो एक इंटरफ़ेस दूसरे इंटरफ़ेस में नेस्टेड है)।
पाओलो एबरमन जू

4
मुझे पता है कि यह एक पुराना विषय है, लेकिन मैं बाहरी पैकेज को अपने पैकेज में रखना पसंद करूंगा और किसी भी पूरक इंटरफेस (जैसे Map.Entry) या कक्षाएं भी उस पैकेज के भीतर हो सकता हूं । मैं यह कहता हूं क्योंकि मैं अपनी कक्षाओं को छोटा और बिंदु तक रखना पसंद करता हूं। एक पाठक यह भी देख सकता है कि पैकेज में मौजूद कक्षाओं को देखकर अन्य संस्थाएं किस वर्ग से संबंधित हैं। मैं शायद java.collections.mapनक्शे के लिए एक पैकेज होगा । यह OO और प्रतिरूपकता के बारे में है। java.utilइसमें बहुत ज्यादा है। utilकी तरह है common- एक गंध IMO
डेविड केर

1
@ शैगी: java.utilनिश्चित रूप से इसमें बहुत अधिक है। उस ने कहा, मुझे नहीं लगता कि आप इसे ठीक-ठीक पैकेज में तोड़ रहे हैं, जैसा कि आप सुझाव दे रहे हैं कि यह आदर्श है।
कॉलिनड

1
@DavidKerr मान लीजिए कि आप इस इंटरफ़ेस को java.util.MapEntryइसके स्वयं के पैकेज के बाहर कहते हैं । पहला पलटा: इस वर्ग से संबंधित इंटरफ़ेस क्या हैं? मैं कक्षा में देखता हूं। जब तक javadoc इस इंटरफ़ेस से लिंक नहीं करता, मुझे उनके संबंध का कोई सुराग नहीं है। साथ ही लोग आयात पैकेज को नहीं देखते हैं। सबकी अपनी-अपनी राय है। कोई भी सही नहीं है, कोई भी गलत नहीं है
रेमंड चेनन

@RaymondChenon जो मैंने कहा था उसका कुछ हिस्सा मैप और उससे जुड़ी कक्षाओं जैसे, Map.Entry को एक अलग पैकेज में रखना था, जैसे java.collections.map। इस तरह मानचित्र से संबंधित सभी कोड एक ही स्थान (पैकेज) में हैं और शीर्ष-स्तरीय मानचित्र वर्ग बोझ नहीं है। मैं शायद संबंधित कार्यान्वयन (HashMap, आदि) को एक ही पैकेज में रखूंगा।
डेविड केर

14

सदस्य इंटरफेस स्पष्ट रूप से स्थिर हैं। कोड के शब्दार्थ को बदले बिना आपके उदाहरण में स्थिर संशोधक को हटाया जा सकता है। जावा लैंग्वेज स्पेसिफिकेशन 8.5.1 भी देखें । स्थैतिक सदस्य प्रकार घोषणाएँ


यह एक 'आंतरिक इंटरफ़ेस' नहीं है: यह एक नेस्टेड इंटरफ़ेस है। जावा में इनर का एक विशिष्ट अर्थ है।
लोर्ने की

@ ईजेपी, मैंने विभिन्न ब्लॉगों को परस्पर शब्दों के प्रयोग से पढ़ा। क्या आंतरिक इंटरफ़ेस मौजूद है? वे नेस्टेड इंटरफ़ेस से कैसे अलग हैं?
नंबर 945

@BreakingBenjamin, नेस्टेड इंटरफ़ेस का अर्थ है स्थिर। आंतरिक वर्ग और नेस्टेड वर्ग मौजूद है, लेकिन आंतरिक इंटरफ़ेस नहीं। यदि ऐसा है, तो भी इसे नेस्टेड इंटरफ़ेस कहा जाना चाहिए। आंतरिक - गैर स्थिर और नेस्टेड स्थैतिक है।
सुंदर राजन

9

एक आंतरिक इंटरफ़ेस को एक्सेस करने के लिए स्थिर होना पड़ता है। इंटरफ़ेस वर्ग के उदाहरणों के साथ जुड़ा नहीं है, लेकिन कक्षा के साथ ही, इसलिए इसे इस Foo.Barतरह एक्सेस किया जाएगा :

public class Baz implements Foo.Bar {
   ...
}

ज्यादातर तरीकों से, यह एक स्थिर आंतरिक वर्ग से अलग नहीं है।


35
एक नेस्टेड इंटरफ़ेस स्वचालित रूप से स्थिर है, चाहे कोई कीवर्ड लिखता हो या नहीं।
पाओलो एबरमन जू

3
हमें वास्तव में एक अलग उत्तर को स्वीकार करने के लिए समुदाय को वोट देने का एक तरीका चाहिए: stackoverflow.com/a/74400/632951
पचेरियर


@ ClintonN.Dreisbach क्या आप बता सकते हैं कि The interface isn't associated with instances of the class, but with the class itselfआगे और क्या मतलब है , मुझे यह समझ में नहीं आया
कसुन सियामबलपिटिया

6

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

class ConcreteA implements A {
 :
}

class ConcreteB implements B {
 :
}

class ConcreteC implements C {
 :
}

class Zoo implements A, C {
 :
}

class DoSomethingAlready {
  interface AC extends A, C { }

  private final AC ac;

  DoSomethingAlready(AC ac) {
    this.ac = ac;
  }
}

2
यह बकवास है। वर्ग इंटरफ़ेस को लागू नहींZoo करता है , इसलिए, उदाहरण के निर्माणकर्ता को पारित नहीं किया जा सकता है, जिसकी उम्मीद है । यह तथ्य कि दोनों का विस्तार है, और , इसका मतलब यह नहीं है कि लागू करने वाले वर्ग और जादुई रूप से भी लागू होते हैं । ACZooDoSomethingAlreadyACACACACAC
होल्गर

3

अपने प्रश्न का बहुत सीधा उत्तर देने के लिए, Map.Entry को देखें।

Map.Entry

यह भी उपयोगी हो सकता है

स्टेटिक नेस्टेड इन्र्फफेसेस ब्लॉग एंट्री


4
यह एक उदाहरण है, लेकिन वास्तव में जवाब नहीं है।
पाओलो एबरमन

मैं "जोड़ी" वस्तुओं को बनाने के लिए Map.Entry का उपयोग करता हूं। यह उजागर है। Pair के कार्यान्वयन में विचारों के दो स्कूल हैं, लेकिन यहाँ बात नहीं है। Map.Entry आंतरिक हो सकता है लेकिन मैं इसे बाहर का उपयोग करें।
रविन्द्रनाथ अकिला

0

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


'स्टेटिक इनर ’शब्दों में एक विरोधाभास है। नेस्टेड कक्षाएं या तो स्थिर या आंतरिक हैं।
लोर्न

0

यदि आप क्लास फू को इंटरफेस में बदलेंगे तो उपरोक्त उदाहरण में "पब्लिक" कीवर्ड को भी बेमानी होगा क्योंकि यह भी बेमानी होगा

एक अन्य इंटरफ़ेस के अंदर परिभाषित इंटरफ़ेस सार्वजनिक रूप से स्थिर होगा।


सवाल का जवाब नहीं दिया
बारिश

0

1998 में, फिलिप वाडलर ने स्थिर इंटरफेस और गैर-स्थिर इंटरफेस के बीच अंतर का सुझाव दिया।

जहाँ तक मैं देख सकता हूँ, इंटरफ़ेस को गैर-स्थिर बनाने में एकमात्र अंतर यह है कि इसमें अब गैर-स्थिर आंतरिक वर्ग शामिल हो सकते हैं; इसलिए परिवर्तन किसी भी मौजूदा जावा प्रोग्राम को अमान्य नहीं करेगा।

उदाहरण के लिए, उन्होंने अभिव्यक्ति समस्या का एक समाधान प्रस्तावित किया , जो एक ओर अभिव्यक्ति के बीच बेमेल है "दूसरी ओर आपकी भाषा में आप जो प्रतिनिधित्व करने का प्रयास कर रहे हैं" के रूप में अभिव्यक्ति "आपकी भाषा कितनी व्यक्त कर सकती है"। ।

उनके नमूना कोड में स्थिर और गैर-स्थिर नेस्टेड इंटरफेस के बीच अंतर का एक उदाहरण देखा जा सकता है :

// This code does NOT compile
class LangF<This extends LangF<This>> {
    interface Visitor<R> {
        public R forNum(int n);
    }

    interface Exp {
        // since Exp is non-static, it can refer to the type bound to This
        public <R> R visit(This.Visitor<R> v);
    }
}

उनके सुझाव ने इसे जावा 1.5.0 में कभी नहीं बनाया। इसलिए, अन्य सभी उत्तर सही हैं: स्थिर और गैर-स्थिर नेस्टेड इंटरफेस में कोई अंतर नहीं है।


यह ध्यान दिया जाना चाहिए कि यह सब जीजे को संदर्भित करता है जो जावा में जेनरिक के लिए एक बहुत ही शुरुआती प्रोसेसर था।
लोर्न

-1

जावा में, स्थिर इंटरफ़ेस / वर्ग इंटरफ़ेस / वर्ग को एक शीर्ष-स्तरीय वर्ग की तरह उपयोग करने की अनुमति देता है, अर्थात, इसे अन्य वर्गों के लिए घोषित किया जा सकता है। तो, आप कर सकते हैं:

class Bob
{
  void FuncA ()
  {
    Foo.Bar foobar;
  }
}

स्थिर के बिना, उपरोक्त संकलन करने में विफल होगा। इसका लाभ यह है कि आपको इंटरफ़ेस घोषित करने के लिए एक नए स्रोत फ़ाइल की आवश्यकता नहीं है। यह नेत्रहीन रूप से इंटरफ़ेस बार को भी कक्षा Foo में जोड़ता है क्योंकि आपको Foo.Bar लिखना है और इसका मतलब है कि Foo वर्ग Foo.Bar के उदाहरणों के साथ कुछ करता है।

जावा में वर्ग प्रकारों का वर्णन


स्थिर के बिना यह संकलन करता है । The स्टेटिक ’बेमानी है।
लोर्न

@ ईजेपी: उस लेख के अनुसार, जो मैं जुड़ा हुआ था, स्थिर के बिना भीतर का वर्ग केवल मालिक वर्ग द्वारा इस्तेमाल किया जा सकता है और न कि owing वर्ग के बाहर किसी चीज द्वारा। स्थैतिक इसे एक नेस्टेड शीर्ष स्तर की कक्षा बनाता है और इसका उपयोग स्वयं के वर्ग (कम से कम, लेख के अनुसार) के दायरे के बाहर की वस्तुओं द्वारा किया जा सकता है। स्थैतिक पूरी तरह से निरर्थक नहीं है और आंतरिक वर्ग के दायरे को प्रभावित करता है। यह कक्षाओं पर लागू होता है, इंटरफेस हमेशा शीर्ष स्तर की वस्तुओं की तरह कार्य कर सकते हैं (जांच करने के लिए भाषा की युक्ति पढ़ने की आवश्यकता है)। शायद मुझे अपने उत्तर (मेरे खराब) के इंटरफ़ेस और वर्ग भागों को अलग करना चाहिए था।
स्किज़

-6

स्टेटिक का मतलब है कि पैकेज (परियोजना) का कोई भी वर्ग हिस्सा बिना पॉइंटर का उपयोग किए बिना इसे आरोपित कर सकता है। यह स्थिति के आधार पर उपयोगी या बाधा हो सकती है।

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

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

एक-बार रिटर्न और त्वरित गणना या आसान प्राप्त डेटा के लिए स्टेटिक तरीके अच्छे हैं।


1
मुझे पता है कि स्थिर का मतलब क्या है। मैंने अभी तक इसे पहले कभी किसी इंटरफेस पर नहीं देखा है। इसलिए आपका प्रश्न ऑफ टॉपिक है - क्षमा करें
Mo.

1
मुझे लगता है कि उनका जवाब ऑफ टॉपिक है।
कोरे तुगे
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.