एक इंस्ट्रूमेंट एक कंस्ट्रक्टर से अलग कैसे होता है?


82

दूसरे शब्दों में, आपको एक उदाहरण इनिशियलाइज़र की आवश्यकता क्यों होगी? एक रचनाकार पर एक उदाहरण इनिशियलाइज़र लिखने में आपको क्या अंतर या फायदा होता है?


2
इंस्टेंस इनिशियलाइज़र काफी दुर्लभ हैं (जब तक कि आप डबल ब्रेस मुहावरे के लिए किसी से कोड में टकराएं नहीं)।
टॉम हॉकिन -

जवाबों:


109

यह इसे अच्छी तरह से समझाता है:

इंस्टेंस इनिशियलाइज़र जब भी वैरिएबल इनिशियलाइज़र्स का उपयोग करने के लिए एक उपयोगी विकल्प होते हैं:

  • initializer कोड अपवादों को पकड़ना चाहिए, या

  • फैंसी गणना करें जो एक उदाहरण चर आरंभीकरण के साथ व्यक्त नहीं की जा सकती हैं। आप निश्चित रूप से, इस तरह के कोड को हमेशा रचनाकारों में लिख सकते हैं।

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

से: Java में JavaWorld Object initialization


17
दूसरी तरफ आप एक कंस्ट्रक्टर में एक बार कोड लिख सकते हैं और बस इसे अन्य सभी कंस्ट्रक्टर्स से कॉल कर सकते हैं। लेकिन अनाम आंतरिक कक्षाएं एक अच्छा बिंदु बनाती हैं।
Tadeusz Kopec

11
आप इसे अन्य कंस्ट्रक्टर्स से कॉल कर सकते हैं - लेकिन फिर आप फिर से कॉल दोहरा रहे हैं। यदि आप एक नया कंस्ट्रक्टर जोड़ते हैं, तो आपको कॉल को जोड़ना याद रखना होगा। एक उदाहरण इनिशियलाइज़र के साथ ऐसा नहीं है।
टेलोनक्स

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

1
@ javamonkey79: आपको लगता है कि कह रहे हैं कि अगर मैं लेने निर्माता से अधिक प्रारंभकर्ता उदाहरण मेरी कक्षा के लिए, केवल जगह है जहाँ उदाहरण प्रारंभकर्ता उपयोगी होता है जब गुमनाम वर्गों के साथ काम कर रहा है?
realPK

4
@Assambar आप अपने init () विधि में अंतिम फ़ील्ड असाइन नहीं कर सकते हैं, लेकिन आप एक इनिशलाइज़र ब्लॉक में कर सकते हैं।
टिम्मोस

22

वस्तु जीवनचक्र के संदर्भ में, कोई अंतर नहीं है। दोनों का निर्माण समय पर किया जाता है, और तार्किक रूप से प्रारंभिक ब्लॉक को निर्माण का हिस्सा माना जा सकता है।

शब्दार्थ, एक इनिलाइज़र कई कारणों से एक अच्छा उपकरण है:

आरंभीकरण को चर के आरंभ के बगल में आरंभीकरण तर्क रखकर कोड पठनीयता में सुधार कर सकते हैं:

   public class Universe {
       public int theAnswer;
       {
         int SIX = 6;
         int NINE = 7;
         theAnswer = SIX * NINE;
       }

       // a bunch of other vars
   }

बनाम

   public class Universe {
       public int theAnswer;

       // a bunch of other vars

       public Universe() {
         int SIX = 6;
         int NINE = 7;
         theAnswer = SIX * NINE;

         // other constructor logic
       }
   }

इनिशियलाइज़र्स को इनवाइट किया जाता है, भले ही कंस्ट्रक्टर का इस्तेमाल किया जाए।

शुरुआती का उपयोग अनाम आंतरिक कक्षाओं में किया जा सकता है, जहां निर्माणकर्ता नहीं कर सकते।


3
आपके पास जो कुछ भी है, वह तकनीकी रूप से एक "इंस्टेंस वैरिएबल इनिशियलाइज़र" है, न कि "इन्स्टेंस इनिशियलाइज़र" (एक वर्ग के भीतर सीधे नेस्टेड)। JLS तीसरा खंड 8.6 देखें।
टॉम हॉकिन -

इंस्टेंस इनिशियलाइज़र ब्लॉक में एक नाम नहीं है जैसा कि यहाँ दिखाया गया है । है ना? आपने नाम के साथ अपना उदाहरण इनिशलाइज़र कोड चिह्नित किया है theAnswer। क्या वो सही है? या मुझे कुछ याद आ रहा है।
RBT

1
@ आरबीटी theAnswerएक घोषित उदाहरण चर है। यह एक अनाम इनिशियलाइज़र ब्लॉक में आरंभिक है। चर घोषणा के बाद अर्धविराम पर ध्यान दें।
ykaganovich

10

जब आपके पास कई कंस्ट्रक्टर होते हैं और चाहते हैं कि प्रत्येक कंस्ट्रक्टर के लिए कुछ सामान्य कोड निष्पादित किए जाएं तो आप उदाहरण इनिशलाइज़र का उपयोग कर सकते हैं। ऐसा सभी कंस्ट्रक्टरों के लिए कहा जाता है।


4

मैं सामान्य रूप से उदाहरण इनिलाइज़र मुहावरे से बचता हूँ - केवल एक ही वास्तविक लाभ जो वैरिएबल इनिशियलाइज़र्स को देता है वह है अपवाद हैंडलिंग।

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


1
आपको अपने सभी कंस्ट्रक्टर्स में मैन्युअल इनिट विधि को कॉल करना होगा।
Stephan

2
@ अलेक्स गुड पॉइंट, लेकिन चूंकि अधिकांश कंस्ट्रक्टर वाले कई वर्गों के पास सामान्य तर्क होते हैं, वे वैसे भी एक-दूसरे को कॉल करते हैं। कम से कम मेरी अधिकांश कक्षाओं में।
CPerkins

3

कंस्ट्रक्टर्स से अधिक उदाहरण initializers का असली फायदा जब हम एक गुमनाम आंतरिक वर्ग का उपयोग में देखा जाता है

अनाम आंतरिक वर्गों में एक निर्माता नहीं हो सकता है (जैसा कि वे अनाम हैं) , इसलिए वे उदाहरण के लिए शुरुआती के लिए एक बहुत ही प्राकृतिक फिट हैं ।


1

ऑब्जेक्ट निर्माण के समय, यदि हम उदाहरण चर का आरंभ करना चाहते हैं, तो हमें कंस्ट्रक्टर के लिए जाना चाहिए, प्रारंभिक गतिविधि के अलावा यदि हम ऑब्जेक्ट निर्माण के समय कोई गतिविधि करना चाहते हैं तो हमें उदाहरण ब्लॉक के लिए जाना चाहिए।

हम कंस्ट्रक्टर को इंस्टेंस ब्लॉक से रिप्लेस नहीं कर सकते क्योंकि कंस्ट्रक्टर तर्क ले सकता है लेकिन इंस्टेंस ब्लॉक तर्क नहीं ले सकता।

हम उदाहरण ब्लॉक wih कंस्ट्रक्टर को प्रतिस्थापित नहीं कर सकते क्योंकि एक वर्ग में एक से अधिक कंस्ट्रक्टर हो सकते हैं। अगर हम इंस्ट्रूमेंट को कंस्ट्रक्टर से बदलना चाहते हैं तो हर कंस्ट्रक्टर में हमें इंस्टेंस ब्लॉक लिखना होगा क्योंकि रनटाइम के दौरान कंस्ट्रक्टर को हम उम्मीद नहीं कर सकते हैं, यह डुप्लिकेट कोड को अनावश्यक रूप से बढ़ा देगा।

उदाहरण :

class MyClass{

    static int object_count = 0;

    MyClass(){
        object_count++;
    }

    MyClass(int i){

        object_count++;
    }

    void getCount() {

        System.out.println(object_count);
    }

    public static void main(String... args) {
        MyClass one = new MyClass();
        MyClass two = new MyClass(2);
        two.getCount();
    }
}

आउटपुट: 2

class MyClass{

    static int object_count = 0;

    {
        object_count++;
    }

    MyClass(){

    }

    MyClass(int i){     

    }

    void getCount() {

        System.out.println(object_count);
    }

    public static void main(String... args) {
        MyClass one = new MyClass();
        MyClass two = new MyClass(2);
        two.getCount();
    }
}

आउटपुट: 2


0

इनिशिएटिव, कंस्ट्रक्टर्स के बीच कोड साझा करने का तरीका है और यह वैरिएबल डिक्लेरेशन के साथ इनिशियलाइज़र का उपयोग करने पर कोड को अधिक पठनीय बनाता है।

जावा कंपाइलर हर कंस्ट्रक्टर में इनिशियलाइज़र ब्लॉक को कॉपी करता है। इसलिए, इस दृष्टिकोण का उपयोग कई बिल्डरों के बीच कोड के एक ब्लॉक को साझा करने के लिए किया जा सकता है। ओरेकल प्रलेखन

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