1. प्रारंभिक चर

जैसा कि आप पहले से ही जानते हैं, आप अपनी कक्षा में कई चर घोषित कर सकते हैं, और न केवल उन्हें घोषित कर सकते हैं, बल्कि उन्हें उनके प्रारंभिक मूल्यों के साथ तुरंत आरंभ भी कर सकते हैं।

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

कोड टिप्पणी
class Cat
{
   public String name;
   public int age = -1;

   public Cat(String name, int age)
   {
     this.name = name;
     this.age = age;
   }

   public Cat()
   {
     this.name = "Nameless";
   }
}



चर ageको एक प्रारंभिक मान दिया गया है




प्रारंभिक मान अधिलेखित है


आयु चर अपने प्रारंभिक मान को संग्रहीत करता है।
 Cat cat = new Cat("Whiskers", 2);
इसकी अनुमति है: पहले कंस्ट्रक्टर को बुलाया जाएगा
 Cat cat = new Cat();
इसकी अनुमति है: दूसरे कंस्ट्रक्टर को बुलाया जाएगा

निष्पादित होने पर ऐसा होता है Cat cat = new Cat("Whiskers", 2);:

  • एक Catवस्तु निर्मित होती है
  • सभी इंस्टेंस वेरिएबल्स को उनके प्रारंभिक मानों के साथ प्रारंभ किया जाता है
  • कंस्ट्रक्टर को कॉल किया जाता है और उसका कोड निष्पादित किया जाता है।

दूसरे शब्दों में, चर पहले अपने प्रारंभिक मान प्राप्त करते हैं, और उसके बाद ही निर्माता के कोड को निष्पादित किया जाता है।


2. एक वर्ग में चरों के आरंभीकरण का क्रम

कंस्ट्रक्टर के चलने से पहले वेरिएबल्स को केवल इनिशियलाइज़ नहीं किया जाता है - उन्हें एक अच्छी तरह से परिभाषित क्रम में इनिशियलाइज़ किया जाता है: जिस क्रम में उन्हें क्लास में घोषित किया जाता है।

आइए कुछ दिलचस्प कोड देखें:

कोड टिप्पणी
public class Solution
{
   public int a = b + c + 1;
   public int b = a + c + 2;
   public int c = a + b + 3;
}

यह कोड संकलित नहीं होगा, क्योंकि जिस समय aवेरिएबल बनाया गया था, तब तक कोई b और c वेरिएबल्स नहीं हैं। लेकिन आप अपना कोड इस प्रकार लिख सकते हैं - यह कोड संकलित होगा और ठीक चलेगा ।

कोड टिप्पणी
public class Solution
{
   public int a;
   public int b = a + 2;
   public int c = a + b + 3;
}


0
0+2
0+2+3

लेकिन याद रखें कि आपका कोड अन्य डेवलपर्स के लिए पारदर्शी होना चाहिए। इस तरह की तकनीकों का उपयोग न करना बेहतर है, क्योंकि यह कोड की पठनीयता को कम करती है।

यहां हमें याद रखना चाहिए कि वेरिएबल्स को वैल्यू असाइन करने से पहले उनके पास एक डिफॉल्ट वैल्यू होती है। प्रकार के लिए int, यह शून्य है।

जब JVM aवेरिएबल को इनिशियलाइज़ करता है, तो यह केवल int टाइप: 0 के लिए डिफ़ॉल्ट मान असाइन करेगा।

जब यह पहुंचता है b, तो एक चर पहले से ही ज्ञात होगा और उसका मान होगा, इसलिए JVM इसे मान 2 निर्दिष्ट करेगा।

और जब यह cचर तक पहुँचता है, aऔर bचर पहले से ही आरंभ हो जाएंगे, इसलिए JVM आसानी से प्रारंभिक मान की गणना करेगा c: 0 + 2 + 3।

यदि आप किसी विधि के अंदर एक चर बनाते हैं, तो आप इसका उपयोग तब तक नहीं कर सकते जब तक कि आपने इसे पहले कोई मान निर्दिष्ट नहीं किया हो। लेकिन यह कक्षा के चर के लिए सच नहीं है! यदि किसी वर्ग के एक चर के लिए एक प्रारंभिक मान निर्दिष्ट नहीं किया गया है, तो उसे एक डिफ़ॉल्ट मान निर्दिष्ट किया जाता है।


3. स्थिरांक

जबकि हम विश्लेषण कर रहे हैं कि ऑब्जेक्ट कैसे बनाए जाते हैं, यह स्थिरांक के आरंभीकरण पर स्पर्श करने योग्य है, अर्थात finalसंशोधक के साथ चर।

यदि एक चर में finalसंशोधक है, तो उसे एक प्रारंभिक मान निर्दिष्ट किया जाना चाहिए। आप यह पहले से ही जानते हैं, और इसमें आश्चर्य की कोई बात नहीं है।

लेकिन जो आप नहीं जानते हैं वह यह है कि यदि आप इसे कंस्ट्रक्टर में असाइन करते हैं तो आपको तुरंत प्रारंभिक मान असाइन करने की आवश्यकता नहीं है। यह अंतिम चर के लिए ठीक काम करेगा। केवल आवश्यकता यह है कि यदि आपके पास कई कंस्ट्रक्टर हैं, तो प्रत्येक कंस्ट्रक्टर में एक अंतिम चर को एक मान निर्दिष्ट किया जाना चाहिए।

उदाहरण:

public class Cat
{
   public final int maxAge = 25;
   public final int maxWeight;

   public Cat (int weight)
   {
     this.maxWeight = weight; // Assign an initial value to the constant
   }
}


4. कंस्ट्रक्टर में कोड

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

उदाहरण के लिए, यहां कंस्ट्रक्टर्स के बारे में एक महत्वपूर्ण टिप्पणी दी गई है। सिद्धांत रूप में, आप कंस्ट्रक्टर में किसी भी जटिलता का कोड लिख सकते हैं। लेकिन ऐसा मत करो। उदाहरण:

class FilePrinter
{
   public String content;

   public FilePrinter(String filename) throws Exception
   {
      FileInputStream input = new FileInputStream(filename);
      byte[] buffer = input.readAllBytes();
      this.content = new String(buffer);
   }

   public void printFile()
   {
      System.out.println(content);
   }
}






फ़ाइल रीड स्ट्रीम खोलें
फ़ाइल को बाइट सरणी में पढ़ें
बाइट सरणी को स्ट्रिंग के रूप में सहेजें




स्क्रीन पर फ़ाइल की सामग्री प्रदर्शित करें

FilePrinter क्लास कंस्ट्रक्टर में, हमने तुरंत एक फ़ाइल पर एक बाइट स्ट्रीम खोली और उसकी सामग्री को पढ़ा। यह जटिल व्यवहार है और इसके परिणामस्वरूप त्रुटियाँ हो सकती हैं।

अगर ऐसी कोई फाइल नहीं होती तो क्या होता? क्या होगा यदि फ़ाइल पढ़ने में समस्याएँ हों? क्या हुआ अगर यह बहुत बड़ा था?

जटिल तर्क का तात्पर्य त्रुटियों की उच्च संभावना से है और इसका अर्थ है कि कोड को अपवादों को सही ढंग से संभालना चाहिए।

उदाहरण 1 - क्रमांकन

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

लेकिन फिर मान लीजिए कि आपकी फाइल दूसरे कंप्यूटर पर मौजूद नहीं है। कंस्ट्रक्टर में कोई त्रुटि होगी, और कोई भी इसे हैंडल नहीं करेगा। और वह प्रोग्राम को समाप्त करने में काफी सक्षम है।

उदाहरण 2 - एक वर्ग के क्षेत्रों को आरंभ करना

यदि आपका क्लास कंस्ट्रक्टर चेक किए गए अपवादों को फेंक सकता है, यानी कि थ्रो कीवर्ड के साथ चिह्नित किया गया है, तो आपको अपनी वस्तु बनाने वाली विधि में संकेतित अपवादों को पकड़ना होगा।

लेकिन क्या होगा अगर ऐसी कोई विधि नहीं है? उदाहरण:

कोड  टिप्पणी
class Solution
{
   public FilePrinter reader = new FilePrinter("c:\\readme.txt");
}
यह कोड संकलित नहीं होगा।

क्लास कंस्ट्रक्टर एक चेक किए गए अपवाद कोFilePrinter फेंक सकता है , जिसका अर्थ है कि आप किसी ऑब्जेक्ट को ट्राई-कैच ब्लॉक में लपेटे बिना नहीं बना सकते। और एक कोशिश-पकड़ ब्लॉक केवल एक विधि में लिखा जा सकता हैFilePrinter



5. बेस क्लास कंस्ट्रक्टर

पिछले पाठों में, हमने वंशानुक्रम पर थोड़ी चर्चा की थी। दुर्भाग्य से, वंशानुक्रम और OOP की हमारी पूरी चर्चा OOP को समर्पित स्तर के लिए आरक्षित है, और निर्माणकर्ताओं की विरासत हमारे लिए पहले से ही प्रासंगिक है।

यदि आपकी कक्षा किसी अन्य वर्ग को प्राप्त करती है, तो मूल वर्ग का एक ऑब्जेक्ट आपकी कक्षा के किसी ऑब्जेक्ट के अंदर एम्बेड किया जाएगा। क्या अधिक है, मूल वर्ग के अपने चर और अपने स्वयं के निर्माता हैं।

इसका मतलब यह है कि आपके लिए यह जानना और समझना बहुत महत्वपूर्ण है कि जब आपकी कक्षा में एक मूल वर्ग होता है और आप इसके चर और विधियों को प्राप्त करते हैं तो चर कैसे आरंभ किए जाते हैं और निर्माणकर्ता कहलाते हैं।

कक्षाओं

हम उस क्रम को कैसे जानते हैं जिसमें वेरिएबल्स प्रारंभ किए गए हैं और कन्स्ट्रक्टर कहलाते हैं? आइए दो वर्गों के लिए कोड लिखकर प्रारंभ करें। एक दूसरे को विरासत में मिलेगा:

कोड टिप्पणी
class ParentClass
{
   public String a;
   public String b;

   public ParentClass()
   {
   }
}

class ChildClass extends ParentClass
{
   public String c;
   public String d;

   public ChildClass()
   {
   }
}










वर्ग वर्ग ChildClass को विरासत में मिला है ParentClass

हमें उस क्रम को निर्धारित करने की आवश्यकता है जिसमें वेरिएबल्स प्रारंभ किए गए हैं और कन्स्ट्रक्टर कहलाते हैं। लॉगिंग हमें ऐसा करने में मदद करेगी।

लॉगिंग

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

यह निर्धारित करना काफी सरल है कि कंस्ट्रक्टर को कॉल किया गया है: कंस्ट्रक्टर के शरीर में, कंसोल को एक संदेश लिखें। लेकिन आप कैसे बता सकते हैं कि एक चर प्रारंभ किया गया है या नहीं?

वास्तव में, यह भी बहुत मुश्किल नहीं है: एक विशेष विधि लिखें जो वैरिएबल को इनिशियलाइज़ करने के लिए उपयोग किए गए मान को वापस कर देगी और इनिशियलाइज़ेशन को लॉग कर देगी। कोड ऐसा दिखाई दे सकता है:

अंतिम कोड

public class Main
{
   public static void main(String[] args)
   {
      ChildClass obj = new ChildClass();
   }

   public static String print(String text)
   {
      System.out.println(text);
      return text;
   }
}

class ParentClass
{
   public String a = Main.print("ParentClass.a");
   public String b = Main.print("ParentClass.b");

   public ParentClass()
   {
      Main.print("ParentClass.constructor");
   }
}

class ChildClass extends ParentClass
{
   public String c = Main.print("ChildClass.c");
   public String d = Main.print("ChildClass.d");

   public ChildClass()
   {
      Main.print("ChildClass.constructor");
   }
}




ChildClassएक वस्तु बनाएँ


यह विधि पास किए गए पाठ को कंसोल पर लिखती है और उसे वापस भी करती है। क्लास डिस्प्ले टेक्स्ट को





डिक्लेयर करें और इसके साथ वेरिएबल्स को इनिशियलाइज़ करें। एक संदेश लिखें कि निर्माता को बुलाया गया है। वापसी मूल्य पर ध्यान न दें। क्लास डिस्प्ले टेक्स्ट को डिक्लेयर करें और इसके साथ वेरिएबल्स को इनिशियलाइज़ करें। एक संदेश लिखें कि निर्माता को बुलाया गया है। वापसी मूल्य पर ध्यान न दें। ParentClass









ChildClass






यदि आप इस कोड को निष्पादित करते हैं, तो टेक्स्ट स्क्रीन पर निम्नानुसार प्रदर्शित होगा:

विधि का कंसोल आउटपुटMain.print()
ParentClass.a
ParentClass.b
ParentClass.constructor
ChildClass.c
ChildClass.d
ChildClass.constructor

तो आप हमेशा व्यक्तिगत रूप से सुनिश्चित कर सकते हैं कि कन्स्ट्रक्टर को बुलाए जाने से पहले कक्षा के चर प्रारंभ किए जाते हैं। इनहेरिट की गई क्लास के इनिशियलाइज़ेशन से पहले एक बेस क्लास को पूरी तरह से इनिशियलाइज़ किया जाता है।