हम सभी जानते हैं कि " किसी भी वर्ग के सभी उदाहरण एक ही java.lang.Class को उस प्रकार के वर्ग के शेयर करते हैं "
जैसे)
Student a = new Student();
Student b = new Student();
तब a.getClass() == b.getClass()
सच है।
अब मान लीजिए
Teacher t = new Teacher();
बिना जेनेरिक के संभव नहीं है।
Class studentClassRef = t.getClass();
लेकिन यह अब गलत है ..?
उदा) के public void printStudentClassInfo(Class studentClassRef) {}
साथ बुलाया जा सकता हैTeacher.class
जेनरिक का इस्तेमाल करके इससे बचा जा सकता है।
Class<Student> studentClassRef = t.getClass(); //Compilation error.
अब T क्या है ?? टी टाइप पैरामीटर (जिसे टाइप वैरिएबल भी कहा जाता है); कोण कोष्ठक (<>) द्वारा सीमांकित, वर्ग नाम का अनुसरण करता है।
टी केवल एक प्रतीक है, वर्ग फ़ाइल के लेखन के दौरान घोषित एक चर नाम (किसी भी नाम हो सकता है) की तरह। बाद में टी को
आरंभिक ( HashMap<String> map = new HashMap<String>();
) के दौरान मान्य वर्ग नाम से प्रतिस्थापित किया जाएगा।
जैसे) class name<T1, T2, ..., Tn>
तो Class<T>
विशिष्ट वर्ग प्रकार ' T
' के एक वर्ग वस्तु का प्रतिनिधित्व करता है ।
मान लें कि आपके वर्ग के तरीकों को नीचे की तरह अज्ञात प्रकार के मापदंडों के साथ काम करना है
/**
* Generic version of the Car class.
* @param <T> the type of the value
*/
public class Car<T> {
// T stands for "Type"
private T t;
public void set(T t) { this.t = t; }
public T get() { return t; }
}
यहाँ T का उपयोग CarName केString
रूप में किया जा सकता है
या टी Integer
को मॉडलनंबर के रूप में इस्तेमाल किया जा सकता है ,
या टी Object
को वैध कार उदाहरण के रूप में इस्तेमाल किया जा सकता है ।
अब यहाँ ऊपर सरल POJO है जिसका उपयोग रनटाइम के दौरान अलग-अलग तरीके से किया जा सकता है।
संग्रह उदाहरण) सूची, सेट, हैशमैप सबसे अच्छे उदाहरण हैं जो टी की घोषणा के अनुसार विभिन्न वस्तुओं के साथ काम करेंगे, लेकिन एक बार जब हमने टी को स्ट्रिंग के रूप में घोषित किया
) HashMap<String> map = new HashMap<String>();
तो यह केवल स्ट्रिंग क्लास उदाहरण वस्तुओं को स्वीकार करेगा।
सामान्य तरीके
जेनेरिक विधियां ऐसी विधियां हैं जो अपने प्रकार के मापदंडों का परिचय देती हैं। यह एक सामान्य प्रकार की घोषणा करने के समान है, लेकिन प्रकार पैरामीटर्स का दायरा उस विधि तक सीमित है जहां यह घोषित किया गया है। स्थैतिक और गैर-स्थिर जेनेरिक विधियों की अनुमति है, साथ ही जेनेरिक वर्ग के निर्माणकर्ता भी।
जेनेरिक विधि के लिए सिंटैक्स में एक प्रकार का पैरामीटर होता है, कोण कोष्ठक के अंदर, और विधि के रिटर्न प्रकार से पहले प्रकट होता है। जेनेरिक तरीकों के लिए, विधि के रिटर्न प्रकार से पहले टाइप पैरामीटर सेक्शन दिखाई देना चाहिए।
class Util {
// Generic static method
public static <K, V, Z, Y> boolean compare(Pair<K, V> p1, Pair<Z, Y> p2) {
return p1.getKey().equals(p2.getKey()) &&
p1.getValue().equals(p2.getValue());
}
}
class Pair<K, V> {
private K key;
private V value;
}
यहां <K, V, Z, Y>
विधि तर्कों में उपयोग किए जाने वाले प्रकारों की घोषणा है जो कि वापसी प्रकार से पहले होनी चाहिए जो boolean
यहां है।
नीचे में; <T>
विधि स्तर पर टाइप घोषणा की आवश्यकता नहीं है, क्योंकि यह पहले से ही कक्षा स्तर पर घोषित किया गया है।
class MyClass<T> {
private T myMethod(T a){
return a;
}
}
लेकिन नीचे वर्ग के प्रकार के मापदंडों के रूप में गलत है K, V, Z, और Y का उपयोग स्थिर संदर्भ (स्थिर विधि) में नहीं किया जा सकता है।
class Util <K, V, Z, Y>{
// Generic static method
public static boolean compare(Pair<K, V> p1, Pair<Z, Y> p2) {
return p1.getKey().equals(p2.getKey()) &&
p1.getValue().equals(p2.getValue());
}
}
अन्य वैध स्कोरर हैं
class MyClass<T> {
//Type declaration <T> already done at class level
private T myMethod(T a){
return a;
}
//<T> is overriding the T declared at Class level;
//So There is no ClassCastException though a is not the type of T declared at MyClass<T>.
private <T> T myMethod1(Object a){
return (T) a;
}
//Runtime ClassCastException will be thrown if a is not the type T (MyClass<T>).
private T myMethod1(Object a){
return (T) a;
}
// No ClassCastException
// MyClass<String> obj= new MyClass<String>();
// obj.myMethod2(Integer.valueOf("1"));
// Since type T is redefined at this method level.
private <T> T myMethod2(T a){
return a;
}
// No ClassCastException for the below
// MyClass<String> o= new MyClass<String>();
// o.myMethod3(Integer.valueOf("1").getClass())
// Since <T> is undefined within this method;
// And MyClass<T> don't have impact here
private <T> T myMethod3(Class a){
return (T) a;
}
// ClassCastException for o.myMethod3(Integer.valueOf("1").getClass())
// Should be o.myMethod3(String.valueOf("1").getClass())
private T myMethod3(Class a){
return (T) a;
}
// Class<T> a :: a is Class object of type T
//<T> is overriding of class level type declaration;
private <T> Class<T> myMethod4(Class<T> a){
return a;
}
}
और अंत में स्थैतिक विधि को हमेशा स्पष्ट <T>
घोषणा की आवश्यकता होती है ; यह वर्ग स्तर से व्युत्पन्न नहीं होगा Class<T>
। इसका कारण है कि कक्षा स्तर T उदाहरण के लिए बाध्य है।
जेनरिक पर प्रतिबंध भी पढ़ें
वाइल्डकार्ड और सबटाइपिंग
जेनेरिक पद्धति के लिए तर्क टाइप करें