2012-05-09 32 views
7

मैं जावा पर एक परीक्षा कल था। ऐसा कुछ है जो वास्तव में मेरे लिए अस्पष्ट लगता है।गैर स्थैतिक कन्स्ट्रक्टर के लिए स्टेटिक विधि का उपयोग?

नियम सरल हैं:

  1. स्टेटिक विधि गैर स्थिर तरीकों नहीं फोन नहीं कर सकते हैं कर सकते हैं।
  2. कन्स्ट्रक्टर्स विधि प्रकार के बिना वापसी प्रकार के प्रकार हैं।

    public class Main { 
        public static void main(String[] args) { 
         Main p = new Main(); 
         k(); 
        } 
    
        protected Main() { 
         System.out.print("1234"); 
        } 
    
        protected void k() { 
        } 
    } 
    
    Main p = new Main() line prints 1234 
    k() line raises error 
    

तो क्यों हुआ? क्या यह ऊपर जावा के नियमों के साथ संघर्ष नहीं करता है?

+3

यदि किसी स्थिर विधि से कन्स्ट्रक्टर को कॉल करना असंभव था, तो आप कभी भी किसी ऑब्जेक्ट का निर्माण नहीं कर सके। –

उत्तर

10

1 - स्टेटिक विधि गैर स्थैतिक तरीकों को कॉल नहीं कर सकता है।

ज़रूर वे कर सकते हैं, लेकिन वे पर विधि कॉल करने के लिए एक वस्तु की जरूरत

एक स्थिर विधि में, this संदर्भ उपलब्ध नहीं है, इसलिए foo() (जो this.foo() के बराबर है) अवैध है।

2 - रचनाकार कोई प्रकार का तरीका नहीं है जिसमें कोई वापसी प्रकार नहीं है।

अगर वे compared to methods होना चाहिए, मैं कहूंगा कि कंस्ट्रक्टर्स गैर स्थिर तरीकों के करीब (वास्तव में एक निर्माता के अंदर एक this संदर्भ है के बाद से) कर रहे हैं।

इस दृश्य को देखते हुए, यह आपको स्पष्ट होना चाहिए कि एक स्थिर विधि बिना किसी समस्या के कन्स्ट्रक्टर को क्यों कॉल कर सकती है।


इसलिए, यह योग करने के लिए ऊपर:

Main p = new Main(); 

ठीक है, new Main() के बाद से किसी भी मौजूदा वस्तु पर निर्भर नहीं करता। के बाद से यह this.k() के बराबर है और this अपने (स्थिर) मुख्य विधि में उपलब्ध नहीं है

k(); 

ठीक नहीं है।

+0

हर समय लोगों को क्या भ्रमित करता है यह तथ्य है कि 'नया मुख्य() 'एक साधारण कन्स्ट्रक्टर कॉल नहीं है - यह यूनरी ऑपरेटर' नया 'का आवेदन है जबकि यह निर्दिष्ट करता है कि कौन सा कन्स्ट्रक्टर ** को कॉल करने के लिए कहता है व्यापक आवंटन + प्रारंभिक प्रक्रिया **। –

+0

@MarkoTopolnik, जेएलएस संदर्भ? – aioobe

+0

क्या आपको वाकई इसकी आवश्यकता है, क्योंकि यह स्पष्ट है? 'नया' लागू करना ** ढेर से स्मृति आवंटित करता है ** - यह एक के लिए, कन्स्ट्रक्टर में लिखा नहीं है।यह ** सभी इंस्टेंस प्रारंभकर्ता ** को भी कॉल करता है - एक और तथ्य निश्चित रूप से आपके लिए स्पष्ट है। यह कन्स्ट्रक्टर कोड में कहीं भी लिखा नहीं है। यह कन्स्ट्रक्टर द्वारा 'इस' के साथ कन्स्ट्रक्टर को भी परिभाषित करता है - कॉलर द्वारा नहीं, बल्कि निहित कोड द्वारा। कन्स्ट्रक्टर कुछ भी नहीं बल्कि कॉलबैक है। –

4

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

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

कुछ स्पष्टीकरण:

स्टेटिक विधि गैर स्थिर तरीकों नहीं फोन नहीं कर सकते हैं कर सकते हैं।

काफी नहीं। आप एक स्थैतिक विधि के अंदर से एक गैरस्टिक विधि को कॉल कर सकते हैं, बस आपको उस वर्ग की विशिष्ट वस्तु पर स्कोप की आवश्यकता है। अर्थात।

p.k(); 

उपरोक्त आपके कोड नमूने में पूरी तरह से काम करेगा।

कॉल

k(); 

एक उदाहरण (nonstatic) विधि के अंदर ठीक होगा। और यह

this.k(); 

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

5

नियम सरल हैं:
1 - स्टेटिक विधि गैर स्थिर तरीकों नहीं फोन नहीं कर सकते हैं कर सकते हैं।

यह बस सच नहीं है। एक स्थिर विधि एक "लक्ष्य" संदर्भ के माध्यम से, एक गैर स्थैतिक विधि को कॉल कर सकता है। उदाहरण के लिए, यह एक स्थिर विधि में ठीक है:

Integer x = Integer.valueOf(10); 
int y = x.intValue(); // Instance method! 

असली बिंदु "एक स्थिर विधि के भीतर कोई this संदर्भ नहीं है" है।

2 - रचनाकार कोई प्रकार का तरीका नहीं है जिसमें कोई वापसी प्रकार नहीं है।

यह ईमानदार होने के लिए वास्तव में उपयोगी मॉडल नहीं है। यह और समझ (कॉलर के दृष्टिकोण से) एक कन्स्ट्रक्टर को एक रिटर्न प्रकार के साथ एक स्थिर विधि के रूप में मानने के लिए बनाता है जो घोषित वर्ग के समान है, लेकिन यह किसी भी माध्यम से एक आदर्श मॉडल नहीं है।

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

+0

कन्स्ट्रक्टर को एक शून्य-वापसी कॉलबैक की तुलना करने के बारे में क्या लगता है जिसे ऑब्जेक्ट प्रारंभिकरण के हिस्से के रूप में बुलाया जाता है? संकेत का वह स्तर एक बात है कि, मेरे दिमाग में, लोगों से बच निकलता है और गलत धारणाएं पैदा करता है। –

+0

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

+0

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