Java Generics

Introduction to Java Generics

यदि में आप से कहु की में ऐसा addition का method बना सकता हुँ जो हर तरीके के data type के variables को add कर सकता है। हर data type से मेरा मतलब है यदि में चाहूँ तो integers add कर लू और उसी method से double भी add कर लू । आप पुछेंगे क्या ऐसा करना possible है??. जी हाँ बिलकुल possible है। ऐसा method आसानी से बनाया जा सकता है। और में ही नहीं हर कोई बना सकता है।

Generics की मदद से आप ऐसा method बना सकते है जो हर तरह के data type के साथ execute कर सकते है। इन methods में आप data type को parameters की तरह pass करते है। इससे compiler को पता चलता है की किस तरह के data type के साथ method को execute करना है।

Java का ये feature readability बढ़ाता है, programmers का time बचाता है और computer की memory भी बचाता है। क्योंकि आपको हर तरह के data type के लिए अलग से code लिखने की जरुरत नहीं होती है।

Generics को केवल reference types (class) के साथ ही यूज़ किया जा सकता है। आप कोई primitive types जैसे की int और char आदि के साथ generics को यूज़ नहीं कर सकते है। इसलिए java में सभी primitive types को class के रूप में implement किया गया है। जैसे की int के लिए Integer और double के Double आदि।

केवल methods ही नहीं आप classes, interfaces और constructors को भी generic बना सकते है।

Generic class का structure निचे दिया जा रहा है।

class GenWorld<T>
{

}

जब आप इस क्लास का object क्रिएट करेंगे तो उसका structure कुछ ऐसा होगा -

GenWorld<Integer> obj1 = new GenWorld<Integer>(20);

Example of Java Generics:

class GenWorld<T>
{
    T getValue;
     public GenWorld(T n)
     {
               this.getValue=n;
     }

      public void display()
      {
            System.out.println(this.getValue);
       }
}

public class GenDemo
{
    public static void main(String args[])
    {
            GenWorld<Integer> = intgen = new GenWorld<Integer>(10);
            GenWorld<String> Stringgen = new GenWorld<String>(“vipin”);
            intgen.display();
            Stringgen.display();
      }
}

ऊपर दिए उदाहरण में जैसा की आप देख सकते है class को अलग तरह से declare किया गया है। यंहा पर हमने class के नाम के आगे (< >) brackets में generic टाइप declare किया है। ये दिखता है की हमारी क्लास generic है।

अब आप variable declaration को देखिये यंहा पर हमारे variable का type generic है जो की हमने ऊपर क्लास क्रिएट करते समय बनाया था।

इसके बाद एक constructor डिक्लेअर किया गया है जिसमे generic argument पास हो रहा। असल में जब आप object create करेंगे तो जिस भी टाइप का डेटा आप डालेंगे ये उसी में convert हो जायेगा। यही यदि आप इन्टिजर डालेंगे तो ये इन्टिजर हो जायेगा और स्ट्रिंग डालेंगे तो स्ट्रिंग।

अब आते है सबसे महत्वपूर्ण बात पर जैसे आप देख सकते है की generic class के ऑब्जेक्ट थोड़ी different तरीके से क्रिएट किये जाते है। आप जिस तरह का डेटा argument में पास करने वाले है वो आपको object क्रिएट करते समय बताना होता है. जैसे की मैने ऊपर दिए गए उदाहरण में किया है।

Generic Methods

जैसा की आपने ऊपर दिए हुए example में देखा के एक generic class का method generic type को यूज़ कर सकता है इसलिए वह method भी generic ही होता है। लेकिन यदि आप चाहे तो किसी ऐसी class में भी generic method declare कर सकते है जो खुद generic नहीं है। Generic methods क्रिएट करने के लिए structure निचे दिया जा रहा है।

<T> void myMethod(T x)
{
     T a = x;

     System.out.println("hello",a);
}

Generic Constructor

Classes और methods के साथ साथ आप constructors को भी generic declare कर सकते है। ये ठीक ऐसे ही होता है जैसे आपने methods को generic declare किया था। Constructor के generic होने के लिए class का generic होना आवश्यक नहीं है। इसका उदाहरण निचे दिया जा रहा है -

class GenWorld
{
   public <T>GenWorld(T arg)
   {
       // this is is a generic constructor
   }
}

Generic Interfaces

Classes, methods और constructors की तरह ही आप interfaces को भी generic declare कर सकते है। इसका तरीका बिलकुल simple है।

public interface myInterface<T>
{
    public T myFunction();
}

public class myClass implements myInterface<T>
{
    public T myFunction()
    {
      //
    }
}

Bounded Types

ऊपर दिए गए उदाहरण में आप T को किसी भी data type से replace कर सकते है ऐसा करना ठीक है लेकिन कभी ऐसा भी हो सकता है जब चाहे की यूज़र सिर्फ numbers ही पास करे। मतलब आप यूज़र को numbers के अलावा कोई भी data type pass करने से रोकना चाहते है।

ऐसी situation को handle करने के लिए java bounded types provide करती है। Type parameter(T) declare करते समय आप जो type आप यूज़ करना चाहते है उसकी super class को extend करते है। ऐसा करने से T को सिर्फ उसी super class के types के द्वारा replace किया जा सकता है। इसका structure निचे दिया जा रहा है -

class GenWorld<T extends Number>
{
    // इस class में आप T की जगह सिर्फ numbers ही यूज़ कर सकते है।  
}

Wildcard Arguments

एक बार आप जब किसी generic क्लास का एक particular type argument के द्वारा object क्रिएट करते है तो आपका वह object generic न होकर एक particular type का हो जाता है। ऊपर दिए गए उदाहरण को यदि आप देखे तो intgen एक generic type नहीं है क्योंकि इसे integer argument के साथ क्रिएट किया गया है। इसलिए intgen और stringgen दोनों अलग अलग तरह के object है इनको आप उसी क्लास के किसी दूसरे object को refer नहीं कर सकते है। लेकिन यदि वो object भी integer type argument के साथ create किया गया है तो आप ऐसा कर सकते है।

अब आप सोचिये की आप generic क्लास के हर object को print करवाना चाहते है उसके लिए आप एक function बनाते है जो object को argument की तरह लेता है और print करवाता है। इसके लिए आप ऐसा करेंगे।

void dispObj(GenWorld<T> obj) // can not do this, because all object are not allowed with this statement and function checks for strings only.
{
  //
}   

जैसा की ऊपर दिया गया है आप ऐसा ही कुछ करने का प्रयास करेंगे लेकिन ये गलत होगा क्योंकि सभी object pass नहीं किये जा सकते है। इस जगह पर आप wildcard arguments यूज़ कर सकते है और function के अंदर किसी भी तरह के object को print करवा सकते है। Wildcard का structure और उदाहरण निचे दिए जा रहे है।

void dispObj(GenWorld<?> obj)
{

}