CodeGym /Java Blog /अनियमित /जावा में जेनरिक
John Squirrels
स्तर 41
San Francisco

जावा में जेनरिक

अनियमित ग्रुप में प्रकाशित
नमस्ते! हम Java Generics के बारे में बात करने जा रहे हैं। मुझे कहना होगा कि आप बहुत कुछ सीखेंगे! न केवल यह पाठ, बल्कि अगले कुछ पाठ भी जेनरिक को समर्पित होंगे। इसलिए, यदि आप जेनरिक में रुचि रखते हैं, तो आज का दिन आपके लिए भाग्यशाली है: आप जेनरिक की विशेषताओं के बारे में बहुत कुछ जानेंगे। और यदि नहीं, तो इस्तीफा दे दो और आराम करो! :) यह एक बहुत ही महत्वपूर्ण विषय है, और आपको इसे जानने की जरूरत है। आइए सरल से शुरू करें: "क्या" और "क्यों"।

जावा जेनरिक क्या हैं?

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

import java.util.ArrayList;
import java.util.List;

public class Main {

   public static void main(String[] args) {

       List<String> myList1 = new ArrayList<>();
       myList1.add("Test String 1");
       myList1.add("Test String 2");
   }
}
जैसा कि आप अनुमान लगा सकते हैं, इस सूची की एक विशेषता यह है कि हम इसमें सब कुछ नहीं भर सकते हैं: यह विशेष रूप से स्ट्रिंग वस्तुओं के साथ काम करती है। अब जावा के इतिहास में थोड़ा विषयांतर करते हैं और "क्यों?" प्रश्न का उत्तर देने का प्रयास करते हैं। ऐसा करने के लिए, हम ArrayList वर्ग का अपना सरलीकृत संस्करण लिखेंगे। हमारी सूची केवल यह जानती है कि आंतरिक सरणी से डेटा को कैसे जोड़ा और पुनर्प्राप्त किया जाए:

public class MyListClass {

   private Object[] data;
   private int count;

   public MyListClass() {
       this.data = new Object[10];
       this.count = 0;
   }

   public void add(Object o) {
       this.data[count] = o;
       count++;
   }

   public Object[] getData() {
       return data;
   }
}
मान लीजिए हम चाहते हैं कि हमारी सूची केवल Integers को संग्रहीत करे । हम एक सामान्य प्रकार का उपयोग नहीं कर रहे हैं। हम ऐड () विधि में एक स्पष्ट " पूर्णांक का उदाहरण " चेक शामिल नहीं करना चाहते हैं । यदि हमने किया, तो हमारी पूरी कक्षा केवल इंटेगर के लिए उपयुक्त होगी , और हमें दुनिया में हर दूसरे डेटा प्रकार के लिए समान वर्ग लिखना होगा! हम अपने प्रोग्रामरों पर भरोसा करेंगे, और यह सुनिश्चित करने के लिए कोड में केवल एक टिप्पणी छोड़ देंगे कि वे कुछ भी नहीं जोड़ते हैं जो हम नहीं चाहते हैं:

// Use this class ONLY with the Integer data type
public void add(Object o) {
   this.data[count] = o;
   count++;
}
प्रोग्रामरों में से एक ने इस टिप्पणी को याद किया और अनजाने में कई स्ट्रिंग्स को संख्याओं की सूची में डाल दिया और फिर उनकी राशि की गणना की:

public class Main {

   public static void main(String[] args) {

       MyListClass list = new MyListClass();
       list.add(100);
       list.add(200);
       list.add("Lolkek");
       list.add("Shalala");

       Integer sum1 = (Integer) list.getData()[0] + (Integer) list.getData()[1];
       System.out.println(sum1);

       Integer sum2 = (Integer) list.getData()[2] + (Integer) list.getData()[3];
       System.out.println(sum2);
   }
}
कंसोल आउटपुट:

300 
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer 
      at Main.main (Main.java:14)
इस स्थिति का सबसे बुरा हिस्सा क्या है? निश्चित रूप से प्रोग्रामर की लापरवाही नहीं। सबसे बुरी बात यह है कि गलत कोड हमारे कार्यक्रम में एक महत्वपूर्ण स्थान पर समाप्त हो गया और सफलतापूर्वक संकलित हो गया। अब हम बग का सामना कोड लिखते समय नहीं, बल्कि केवल परीक्षण के दौरान करेंगे (और यह सबसे अच्छा मामला परिदृश्य है!) विकास के बाद के चरणों में बग को ठीक करने में बहुत अधिक लागत आती है - पैसे और समय दोनों के मामले में। यह वह जगह है जहाँ जेनेरिक हमें लाभान्वित करते हैं: एक सामान्य वर्ग अशुभ प्रोग्रामर को त्रुटि का तुरंत पता लगाने देता है। कार्यक्रम केवल संकलित नहीं होगा!

import java.util.ArrayList;
import java.util.List;

public class Main {

   public static void main(String[] args) {

       List<Integer> myList1 = new ArrayList<>();
      
       myList1.add(100);
       myList1.add(100);
       myList1.add ("Lolkek"); // Error!
       myList1.add("Shalala"); // Error!
   }
}
प्रोग्रामर को तुरंत अपनी गलती का एहसास होता है और वह तुरंत बेहतर हो जाता है। वैसे, इस प्रकार की त्रुटि को देखने के लिए हमें अपना स्वयं का List वर्ग बनाने की आवश्यकता नहीं थी। बस कोण कोष्ठक हटा दें और टाइप करें ( <Integer> ) एक साधारण ArrayList से!

import java.util.ArrayList;
import java.util.List;

public class Main {

   public static void main(String[] args) {

      List list = new ArrayList();

      list.add(100);
      list.add(200);
      list.add("Lolkek");
      list.add("Shalala");

       System.out.println((Integer) list.get(0) + (Integer) list.get(1));
       System.out.println((Integer) list.get(2) + (Integer) list.get(3));
   }
}
कंसोल आउटपुट:

300 
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer 
     at Main.main(Main.java:16)
दूसरे शब्दों में, जावा के "मूल" तंत्र का उपयोग करके भी, हम इस प्रकार की गलती कर सकते हैं और एक असुरक्षित संग्रह बना सकते हैं। हालाँकि, यदि हम इस कोड को एक IDE में पेस्ट करते हैं, तो हमें एक चेतावनी मिलती है: "अनचेक कॉल टू एड (E) कच्चे प्रकार के java.util.List के सदस्य के रूप में" हमें बताया गया है कि कोई आइटम जोड़ते समय कुछ गलत हो सकता है एक ऐसे संग्रह के लिए जिसमें सामान्य प्रकार का अभाव है। लेकिन "कच्चे प्रकार" वाक्यांश का क्या अर्थ है? कच्चा प्रकार एक सामान्य वर्ग है जिसका प्रकार हटा दिया गया है। दूसरे शब्दों में, सूची myList1 एक अपरिष्कृत प्रकार है । कच्चे प्रकार के विपरीत एक सामान्य प्रकार है - पैरामीटरयुक्त प्रकार के संकेत के साथ एक सामान्य वर्ग । उदाहरण के लिए, सूची <स्ट्रिंग> myList1. आप पूछ सकते हैं कि भाषा कच्चे प्रकारों के उपयोग की अनुमति क्यों देती है ? वजह साफ है। संगतता समस्याओं से बचने के लिए जावा के रचनाकारों ने भाषा में अपरिष्कृत प्रकारों के लिए समर्थन छोड़ दिया। जब तक जावा 5.0 जारी किया गया था (जेनेरिक पहली बार इस संस्करण में दिखाई दिए थे), कच्चे प्रकारों का उपयोग करके बहुत सारे कोड पहले ही लिखे जा चुके थे । नतीजतन, यह तंत्र आज भी समर्थित है। हमने पाठों में जोशुआ बलोच की क्लासिक पुस्तक "प्रभावी जावा" का बार-बार उल्लेख किया है। भाषा के रचनाकारों में से एक के रूप में, उन्होंने अपनी पुस्तक में अपरिष्कृत प्रकारों और सामान्य प्रकारों को नहीं छोड़ा।जावा में जेनरिक क्या हैं?  - 2पुस्तक के अध्याय 23 में एक बहुत ही शानदार शीर्षक है: "नए कोड में कच्चे प्रकारों का उपयोग न करें" यह आपको याद रखने की आवश्यकता है। जेनेरिक कक्षाओं का उपयोग करते समय, कभी भी सामान्य प्रकार को कच्चे प्रकार में न बदलें ।

सामान्य तरीके

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

public class TestClass {

   public static <T> void fill(List<T> list, T val) {
       for (int i = 0; i < list.size(); i++)
           list.set(i, val);
   }

   public static void main(String[] args) {

       List<String> strings = new ArrayList<>();
       strings.add("Old String 1");
       strings.add("Old String 2");
       strings.add("Old String 3");

       fill(strings, "New String");

       System.out.println(strings);

       List<Integer> numbers = new ArrayList<>();
       numbers.add(1);
       numbers.add(2);
       numbers.add(3);

       fill(numbers, 888);
       System.out.println(numbers);
   }
}
सिंटैक्स पर ध्यान दें। यह थोड़ा असामान्य लगता है:

public static <T> void fill(List<T> list, T val)
हम रिटर्न टाइप से पहले <T> लिखते हैं। यह इंगित करता है कि हम एक सामान्य विधि से निपट रहे हैं। इस मामले में, विधि इनपुट के रूप में 2 पैरामीटर स्वीकार करती है: टी ऑब्जेक्ट्स की एक सूची और दूसरी अलग टी ऑब्जेक्ट। <T> का उपयोग करके, हम विधि के पैरामीटर प्रकारों को पैरामीटराइज़ करते हैं: हम स्ट्रिंग्स और एक पूर्णांक की सूची में पास नहीं हो सकते। स्ट्रिंग्स और स्ट्रिंग्स की सूची, पूर्णांकों और पूर्णांकों की सूची, हमारे अपने कैट ऑब्जेक्ट्स की सूची और अन्य कैट ऑब्जेक्ट - यही वह है जो हमें करने की आवश्यकता है। मुख्य () विधि बताती है कि कैसे विभिन्न प्रकार के डेटा के साथ काम करने के लिए भरण () विधि का उपयोग आसानी से किया जा सकता है। सबसे पहले, हम इनपुट के रूप में स्ट्रिंग्स और स्ट्रिंग की सूची के साथ विधि का उपयोग करते हैं, और फिर पूर्णांकों और पूर्णांकों की सूची के साथ। कंसोल आउटपुट:

[New String, New String, New String] [888, 888, 888]
कल्पना कीजिए कि हमारे पास सामान्य तरीके नहीं हैं और 30 विभिन्न वर्गों के लिए भरण () विधि के तर्क की आवश्यकता है। हमें अलग-अलग डेटा प्रकारों के लिए एक ही विधि को 30 बार लिखना होगा! लेकिन सामान्य तरीकों के लिए धन्यवाद, हम अपने कोड का पुन: उपयोग कर सकते हैं! :)

सामान्य वर्ग

आप मानक जावा पुस्तकालयों में प्रदान की जाने वाली सामान्य कक्षाओं तक सीमित नहीं हैं - आप अपना स्वयं का बना सकते हैं! यहाँ एक सरल उदाहरण है:

public class Box<T> {

   private T t;

   public void set(T t) {
       this.t = t;
   }

   public T get() {
       return t;
   }

   public static void main(String[] args) {

       Box<String> stringBox = new Box<>();

       stringBox.set("Old String");
       System.out.println(stringBox.get());
       stringBox.set("New String");

       System.out.println(stringBox.get());
      
       stringBox.set(12345); // Compilation error!
   }
}
हमारा Box<T> वर्ग एक सामान्य वर्ग है। एक बार जब हम निर्माण के दौरान एक डेटा प्रकार ( <T> ) निर्दिष्ट करते हैं, तो हम इसमें अन्य प्रकार की वस्तुओं को रखने में सक्षम नहीं होते हैं। इसे उदाहरण में देखा जा सकता है। अपना ऑब्जेक्ट बनाते समय, हमने संकेत दिया कि यह स्ट्रिंग्स के साथ काम करेगा:

Box<String> stringBox = new Box<>();
और कोड की अंतिम पंक्ति में, जब हम संख्या 12345 को बॉक्स के अंदर डालने का प्रयास करते हैं, तो हमें संकलन त्रुटि मिलती है! इट्स दैट ईजी! हमने अपना स्वयं का सामान्य वर्ग बनाया है! :) इसके साथ ही आज का पाठ समाप्त होता है। लेकिन हम जेनरिक को अलविदा नहीं कह रहे हैं! अगले पाठों में, हम और अधिक उन्नत सुविधाओं के बारे में बात करेंगे, तो आप चले न जाएँ! ) आपने जो सीखा है उसे सुदृढ़ करने के लिए, हमारा सुझाव है कि आप हमारे Java कोर्स का एक वीडियो लेसन देखें
आपकी पढ़ाई में सबसे अच्छी सफलता! :)
टिप्पणियां
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION