क्या जावा स्टैटिक में अनाम आंतरिक कक्षाएं बनाना संभव है?


123

जावा में, नेस्टेड कक्षाएं staticया तो हो सकती हैं या नहीं। यदि वे हैं static, तो वे उदाहरण के सूचक के सूचक के संदर्भ में नहीं होते हैं (उन्हें अब आंतरिक कक्षाएं भी नहीं कहा जाता है, उन्हें नेस्टेड कक्षाएं कहा जाता है)।

एक नेस्टेड वर्ग बनाने के लिए भूल जाते हैं staticजब इसे ज़रूरत नहीं होती है कि संदर्भ कचरा संग्रह या विश्लेषण से बच सकते हैं।

क्या अनाम आंतरिक वर्ग staticको भी बनाना संभव है ? या कंपाइलर इसे स्वचालित रूप से समझ लेता है (जो यह हो सकता है, क्योंकि कोई उपवर्ग नहीं हो सकता है)?

उदाहरण के लिए, यदि मैं एक अनाम तुलनित्र बनाता हूं, तो मुझे लगभग कभी भी बाहर के संदर्भ की आवश्यकता नहीं है:

  Collections.sort(list, new Comparator<String>(){
       int compare(String a, String b){
          return a.toUpperCase().compareTo(b.toUpperCase());
       }
  }

आंतरिक वर्ग को स्थिर बनाने के लिए भूल जाने पर "कचरा संग्रह या पलायन विश्लेषण" के साथ क्या समस्याएं हैं? मुझे लगा कि यह केवल प्रदर्शन के बारे में है ...
टिम ब्यूथ

17
आपका आंतरिक वर्ग उदाहरण इसके बाहरी उदाहरण का संदर्भ रखता है, भले ही आपको इसकी आवश्यकता न हो। इससे कचरा एकत्र होने से सामान रखा जा सकता है। चित्र (संसाधन-भारी) फैक्ट्री ऑब्जेक्ट जो किसी चीज़ के हल्के उदाहरण बनाता है। फैक्ट्री ने अपना काम करने के बाद (जैसे एप्लिकेशन स्टार्टअप के दौरान), इसे निपटाया जा सकता है, लेकिन यह केवल तभी काम करता है जब इसके द्वारा बनाई गई चीजें वापस लिंक न करें।
थिलो

मुझे पता है, यह केवल एक उदाहरण है, लेकिन चूंकि यह एक आवर्ती है, इसलिए यह उल्लेख किया जाना चाहिए कि Collections.sort(list, String.CASE_INSENSITIVE_ORDER)जावा 2 के बाद से काम करता है, पढ़ें, जब से संग्रह एपीआई मौजूद है ...
Holger

जवाबों:


138

नहीं, आप नहीं कर सकते, और नहीं, संकलक यह पता नहीं लगा सकता। यही कारण है कि FindBugs हमेशा अनाम आंतरिक वर्गों को नामांकित वर्गों में बदलने का सुझाव देता है staticयदि वे अपने निहित thisसंदर्भ का उपयोग नहीं करते हैं ।

संपादित करें: टॉम हैटिन - टैकललाइन का कहना है कि यदि अनाम वर्ग को स्थिर संदर्भ (उदाहरण के लिए mainविधि) में बनाया गया है, तो अनाम वर्ग वास्तव में है static। लेकिन जेएलएस असहमत :

एक अनाम वर्ग कभी नहीं होता abstract(.18.1.1.1)। एक अनाम वर्ग हमेशा एक आंतरिक वर्ग होता है (class8.1.3); यह कभी नहीं है static(is8.1.1, never8.5.1)। एक अनाम वर्ग हमेशा अंतर्निहित होता है final(class8.1.1.2)।

रोएडी ग्रीन के जावा शब्दावली का कहना है कि यह तथ्य कि अनाम कक्षाओं को स्थिर संदर्भ में अनुमति दी जाती है, कार्यान्वयन-निर्भर है:

यदि आप अपने कोड को बनाए रखने वालों को रोकना चाहते हैं, तो पता चला है कि वाट्स ने इनिट कोड के javac.exeअंदर अनाम कक्षाओं को अनुमति दी होगी staticऔरstatic विधियों के , भले ही अनाम वर्गों की तुलना में भाषा की कल्पना कभी न हो static। निस्संदेह, इन अनाम वर्गों के पास ऑब्जेक्ट के उदाहरण क्षेत्रों तक कोई पहुंच नहीं है। मैं ऐसा करने की सलाह नहीं देता। सुविधा किसी भी समय निकाला जा सकता है।

संपादित करें 2: JLS वास्तव में ex15.9.2 में अधिक स्पष्ट रूप से स्थिर संदर्भों को शामिल करता है :

चलो सी वर्ग instantiated किया जा रहा हो, और मैं उदाहरण बनाया जा रहा हो। यदि C एक आंतरिक वर्ग है तो मेरे पास तुरंत संलग्न उदाहरण हो सकता है। I (enc8.1.3) का तुरंत संलग्न उदाहरण निम्नानुसार निर्धारित किया जाता है।

  • यदि C एक अनाम वर्ग है, तो:
    • यदि क्लास इंस्टेंस निर्माण अभिव्यक्ति स्थिर संदर्भ (.38.1.3) में होती है, तो मेरे पास तुरंत कोई उदाहरण नहीं है।
    • अन्यथा, के तुरंत enclosing उदाहरण मैं है this

एक स्थैतिक संदर्भ में एक अनाम वर्ग लगभग एक staticनेस्टेड वर्ग के बराबर है , जिसमें यह संलग्न वर्ग का संदर्भ नहीं रखता है, भले ही यह तकनीकी रूप से एक staticवर्ग नहीं है ।


19
फाइंडबग्स के लिए +1 - प्रत्येक जावा डेवलपर को अपने बिल्ड में यह होना चाहिए।
एंड्रयू डफी

13
यह बहुत दुर्भाग्यपूर्ण है, क्योंकि इसका मतलब है कि आप इससे बचना चाह सकते हैं अन्यथा प्रदर्शन कारणों के लिए लगभग संक्षिप्त वाक्यविन्यास।
थिलो

2
JLS 3 जी स्थैतिक संदर्भों में आंतरिक वर्गों के मामले से संबंधित है। वे जेएलएस अर्थों में स्थिर नहीं हैं, लेकिन प्रश्न में दिए गए अर्थों में स्थिर हैं।
टॉम हॉल्टिन

6
यह इस बात पर निर्भर करता है कि यह किस प्रकार कार्यान्वयन पर निर्भर है: यह कोडtrue javac (sun-jdk-1.7.0_10) और falseग्रहण संकलक का उपयोग करके प्रिंट करता है।
पॉल बेलोरा

1
@MichaelMyers मैंने 'इस' संदर्भ का उपयोग किए बिना एक अनाम इनर करने के लिए मुझे ढूंढने के लिए FindBugs का अनुकरण करने की कोशिश की है, और कुछ भी नहीं होता है। क्या आप यह प्रदर्शित कर सकते हैं कि FindBugs आपको सतर्क करते हैं जैसा कि आपने अपने उत्तर की शुरुआत में कहा था? बस कुछ लिंक पेस्ट करें या कभी भी।
फुफिर हवत

15

एक प्रकार का। एक स्थैतिक विधि में निर्मित एक अनाम आंतरिक वर्ग स्पष्ट रूप से प्रभावी रूप से स्थिर होगा क्योंकि इस बाहरी के लिए कोई स्रोत नहीं है।

स्थिर संदर्भों और स्थिर नेस्टेड वर्गों में आंतरिक वर्गों के बीच कुछ तकनीकी अंतर हैं। यदि आप रुचि रखते हैं, तो JLS तीसरा संस्करण पढ़ें।


वास्तव में, मैंने उसे वापस लिया; JLS असहमत है। java.sun.com/docs/books/jls/third%5Fedition/html/… : "एक अनाम वर्ग हमेशा एक आंतरिक वर्ग होता है; यह कभी स्थिर नहीं होता है।"
माइकल मायर्स

1
सवाल में एक अलग अर्थ में स्थिर।
टॉम हॉकिन

1
मैं, थोड़ा स्पष्टीकरण जोड़ा गया है।
टॉम हॉल्टिन

15

मुझे लगता है कि यहाँ नामकरण में थोड़ा भ्रम है, जो वास्तव में बहुत मूर्खतापूर्ण और भ्रमित करने वाला है।

आप जो भी उन्हें कहते हैं, ये पैटर्न (और विभिन्न दृश्यता के साथ कुछ भिन्नताएं) सभी संभव, सामान्य, कानूनी जावा हैं।

public class MyClass {
  class MyClassInside {
  }
}

public class MyClass {
  public static class MyClassInside {
  }
}

public class MyClass {
  public void method() {
    JComponent jc = new JComponent() {
      ...
    }
  }
}

public class MyClass {
  public static void myStaticMethod() {
    JComponent jc = new JComponent() {
      ...
    }
  }
}

उन्हें भाषा युक्ति के लिए कैटर किया जाता है (यदि आप वास्तव में परेशान हैं, तो स्थैतिक विधि के अंदर वाले भाग के लिए खंड 15.9.5.1 देखें)।

लेकिन यह उद्धरण केवल स्पष्ट गलत है :

javac.exe स्थिर इनिट कोड और स्थिर विधियों के अंदर अनाम कक्षाओं की अनुमति देगा, भले ही अनाम कक्षाओं की तुलना में भाषा की कल्पना कभी स्थिर न हो

मुझे लगता है कि उद्धृत लेखक स्थिर संदर्भ के साथ स्थिर कीवर्ड को भ्रमित कर रहा है । (जाहिर है, JLS भी इस संबंध में थोड़ा भ्रमित है।)

ईमानदारी से, उपरोक्त सभी पैटर्न ठीक हैं (जो भी आप उन्हें "नेस्टेड" कहते हैं, "इनर", "अनाम" जो भी हो ...)। वास्तव में, जावा की अगली रिलीज़ में कोई भी इस कार्यक्षमता को अचानक से हटाने वाला नहीं है। ईमानदारी से!


2
"(जाहिर है, JLS भी इस संबंध में थोड़ा भ्रमित है।)" आपको वह अधिकार मिल गया। यह कहने में अजीब लग रहा था कि यह कार्यान्वयन पर निर्भर करता है, लेकिन मुझे याद नहीं है कि पहले जावा शब्दावली में कोई स्पष्ट त्रुटि देखी गई थी। अब से, मैं इसे नमक के दाने के साथ लेता हूं।
माइकल मायर्स

2
हम वास्तव में किसी भी पैटर्न के बारे में बात नहीं कर रहे हैं। हमारा मतलब है कि अनाम नेस्टेड क्लास स्थिर है। यानी आपके तीसरे उदाहरण में newऔर उसके बीच एक "स्थैतिक" जोड़ें JComponent
टिम्मम

मैंने मूल प्रश्न में एक स्पष्टीकरण जोड़ा है कि वह क्या चाहता है।
टिम्मम

@MichaelMyers, JLS में श्रुतलेख को हमेशा व्याख्या करने की आवश्यकता होती है।
पचेरियर

6

आंतरिक कक्षाएं स्थिर नहीं हो सकती हैं - एक स्थिर नेस्टेड वर्ग एक आंतरिक वर्ग नहीं है। जावा ट्यूटोरियल यहां इसके बारे में बात करता है


1
मैंने आधिकारिक नामकरण के संदर्भ में प्रश्न को अद्यतन किया है।
थिलो

0

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


-3

अनाम आंतरिक वर्ग को स्थैतिक विधि के भीतर कॉल करके स्थिर बनाने के नोट पर।

यह वास्तव में संदर्भ को नहीं हटाता है। आप इसका परीक्षण अनाम वर्ग को क्रमबद्ध करने का प्रयास करके कर सकते हैं और संलग्न वर्ग को क्रमबद्ध नहीं बना सकते हैं।


5
-1: एक स्थिर विधि के भीतर एक अनाम वर्ग बनाना वास्तव में बाहरी वर्ग के संदर्भ को दूर करता है । आप इसका परीक्षण अनाम वर्ग को क्रमबद्ध करने का प्रयास करके कर सकते हैं और संलग्न वर्ग को क्रमबद्ध नहीं बना सकते हैं। (मैंने अभी किया।)
ईसाई सेमरा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.