जावा में जेनेरिक: Difference between revisions

From Vigyanwiki
No edit summary
No edit summary
Line 1: Line 1:
{{Short description|Form of abstraction for a type or method to allow them to be functions of a type parameter}}
{{Short description|Form of abstraction for a type or method to allow them to be functions of a type parameter}}
जेनरिक [[सामान्य प्रोग्रामिंग]] की सुविधा है, जिसे 2004 में जावा प्लेटफ़ॉर्म, मानक संस्करण 5.0 के अन्दर [[जावा (प्रोग्रामिंग भाषा)]] में जोड़ा गया था। उन्हें संकलन-समय प्रकार की सुरक्षा प्रदान करते हुए विभिन्न प्रकार की वस्तुओं पर एक प्रकार या विधि को संचालित करने की अनुमति देने के लिए जावा के [[प्रकार प्रणाली]] का विस्तार करने के लिए डिज़ाइन किया गया था।<ref>[http://java.sun.com/j2se/1.5.0/docs/guide/language/index.html Java Programming Language]</ref> पहलू [[संकलन-समय प्रकार की सुरक्षा]] पूरी तरह से प्राप्त नहीं की गई थी, क्योंकि 2016 में यह दिखाया गया था कि सभी स्थितियों में इसकी गारंटी नहीं है।<ref>A ClassCastException can be thrown even in the absence of casts or nulls.{{cite web|url=https://raw.githubusercontent.com/namin/unsound/master/doc/unsound-oopsla16.pdf|title=Java and Scala's Type Systems are Unsound}}</ref>{{sfn|Bloch|2018|loc=Chapter §5 Item 27: Eliminate unchecked warnings|pp=123-125}}
जेनरिक [[सामान्य प्रोग्रामिंग]] की सुविधा है, जिसे 2004 में जावा प्लेटफ़ॉर्म, मानक संस्करण 5.0 के अन्दर [[जावा (प्रोग्रामिंग भाषा)]] में जोड़ा गया था। उन्हें संकलन-समय टाइप की सुरक्षा प्रदान करते हुए विभिन्न टाइप की वस्तुओं पर एक टाइप या विधि को संचालित करने की अनुमति देने के लिए जावा के [[प्रकार प्रणाली|टाइप प्रणाली]] का विस्तार करने के लिए डिज़ाइन किया गया था।<ref>[http://java.sun.com/j2se/1.5.0/docs/guide/language/index.html Java Programming Language]</ref> पहलू [[संकलन-समय प्रकार की सुरक्षा|संकलन-समय टाइप की सुरक्षा]] पूरी तरह से प्राप्त नहीं की गई थी, क्योंकि 2016 में यह दिखाया गया था कि सभी स्थितियों में इसकी गारंटी नहीं है।<ref>A ClassCastException can be thrown even in the absence of casts or nulls.{{cite web|url=https://raw.githubusercontent.com/namin/unsound/master/doc/unsound-oopsla16.pdf|title=Java and Scala's Type Systems are Unsound}}</ref>{{sfn|Bloch|2018|loc=Chapter §5 Item 27: Eliminate unchecked warnings|pp=123-125}}


जावा संग्रह ढाँचा संग्रह उदाहरण में संग्रहीत वस्तुओं के प्रकार को निर्दिष्ट करने के लिए जेनेरिक का समर्थन करता है।
जावा संग्रह ढाँचा संग्रह उदाहरण में संग्रहीत वस्तुओं के टाइप को निर्दिष्ट करने के लिए जेनेरिक का समर्थन करता है।


1998 में, [[गिलाद ब्राचा]], [[ मार्टिन ओडर्सकी |मार्टिन ओडर्सकी]] , डेविड स्टाउटमायर और [[फिलिप वाडलर]] ने जेनेरिक जावा बनाया, जो सामान्य प्रकारों का समर्थन करने के लिए जावा भाषा का विस्तार था।<ref>[http://homepages.inf.ed.ac.uk/wadler/gj/ GJ: Generic Java]</ref> जेनेरिक जावा को [[वाइल्डकार्ड (जावा)]] के साथ जावा में सम्मिलित किया गया था।
1998 में, [[गिलाद ब्राचा]], [[ मार्टिन ओडर्सकी |मार्टिन ओडर्सकी]] , डेविड स्टाउटमायर और [[फिलिप वाडलर]] ने जेनेरिक जावा बनाया, जो सामान्य टाइपों का समर्थन करने के लिए जावा भाषा का विस्तार था।<ref>[http://homepages.inf.ed.ac.uk/wadler/gj/ GJ: Generic Java]</ref> जेनेरिक जावा को [[वाइल्डकार्ड (जावा)]] के साथ जावा में सम्मिलित किया गया था।


==पदानुक्रम और वर्गीकरण==
==पदानुक्रम और वर्गीकरण==
जावा भाषा विशिष्टता के अनुसार:<ref>[http://java.sun.com/docs/books/jls/third_edition/html/j3TOC.html Java Language Specification, Third Edition]
जावा भाषा विशिष्टता के अनुसार:<ref>[http://java.sun.com/docs/books/jls/third_edition/html/j3TOC.html Java Language Specification, Third Edition]
by James Gosling, Bill Joy, Guy Steele, Gilad Bracha – Prentice Hall PTR 2005</ref>
by James Gosling, Bill Joy, Guy Steele, Gilad Bracha – Prentice Hall PTR 2005</ref>
*एक प्रकार का चर अयोग्य पहचानकर्ता है। [[ प्रकार चर |प्रकार चर]] को जेनेरिक क्लास डिक्लेरेशन, जेनेरिक इंटरफ़ेस डिक्लेरेशन, जेनेरिक मेथड डिक्लेरेशन और जेनेरिक कंस्ट्रक्टर डिक्लेरेशन द्वारा प्रस्तुत किया जाता है।
*एक टाइप का चर अयोग्य पहचानकर्ता है। [[ प्रकार चर |टाइप चर]] को जेनेरिक क्लास डिक्लेरेशन, जेनेरिक इंटरफ़ेस डिक्लेरेशन, जेनेरिक मेथड डिक्लेरेशन और जेनेरिक कंस्ट्रक्टर डिक्लेरेशन द्वारा प्रस्तुत किया जाता है।
*वर्ग सामान्य है, यदि वह एक या अधिक प्रकार के चर घोषित करता है।{{sfn|Bloch|2018|loc=Chapter §5 Item 28: Prefer lists to arrays|pp=126-129}} यह एक या अधिक प्रकार के वेरिएबल को परिभाषित करता है, जो पैरामीटर के रूप में कार्य करते हैं।{{sfn|Bloch|2018|loc=Chapter §5 Item 26: Don't use raw types|pp=117-122}} सामान्य वर्ग घोषणा पैरामीटरयुक्त प्रकारों के सेट को परिभाषित करती है, जो प्रकार पैरामीटर अनुभाग के प्रत्येक संभावित आह्वान के लिए एक है। ये सभी पैरामीटरयुक्त प्रकार रनटाइम पर एक ही क्लास साझा करते हैं।
*वर्ग सामान्य है, यदि वह एक या अधिक टाइप के चर घोषित करता है।{{sfn|Bloch|2018|loc=Chapter §5 Item 28: Prefer lists to arrays|pp=126-129}} यह एक या अधिक टाइप के वेरिएबल को परिभाषित करता है, जो पैरामीटर के रूप में कार्य करते हैं।{{sfn|Bloch|2018|loc=Chapter §5 Item 26: Don't use raw types|pp=117-122}} सामान्य वर्ग घोषणा पैरामीटरयुक्त टाइपों के सेट को परिभाषित करती है, जो टाइप पैरामीटर अनुभाग के प्रत्येक संभावित आह्वान के लिए एक है। ये सभी पैरामीटरयुक्त टाइप रनटाइम पर एक ही क्लास साझा करते हैं।
*[[इंटरफ़ेस (जावा)]] सामान्य है यदि यह एक या अधिक प्रकार के चर घोषित करता है।{{sfn|Bloch|2018|loc=Chapter §5 Item 26: Don't use raw types|pp=117-122}} यह एक या अधिक प्रकार के वेरिएबल को परिभाषित करता है, जो पैरामीटर के रूप में कार्य करते हैं।{{sfn|Bloch|2018|loc=Chapter §5 Item 26: Don't use raw types|pp=117-122}} सामान्य इंटरफ़ेस घोषणा प्रकार के सेट को परिभाषित करती है, प्रकार पैरामीटर अनुभाग के प्रत्येक संभावित आह्वान के लिए एक। सभी पैरामीटरयुक्त प्रकार रनटाइम पर समान इंटरफ़ेस साझा करते हैं।
*[[इंटरफ़ेस (जावा)]] सामान्य है यदि यह एक या अधिक टाइप के चर घोषित करता है।{{sfn|Bloch|2018|loc=Chapter §5 Item 26: Don't use raw types|pp=117-122}} यह एक या अधिक टाइप के वेरिएबल को परिभाषित करता है, जो पैरामीटर के रूप में कार्य करते हैं।{{sfn|Bloch|2018|loc=Chapter §5 Item 26: Don't use raw types|pp=117-122}} सामान्य इंटरफ़ेस घोषणा टाइप के सेट को परिभाषित करती है, टाइप पैरामीटर अनुभाग के प्रत्येक संभावित आह्वान के लिए एक। सभी पैरामीटरयुक्त टाइप रनटाइम पर समान इंटरफ़ेस साझा करते हैं।
*विधि सामान्य है यदि यह एक या अधिक प्रकार के चर घोषित करती है।{{sfn|Bloch|2018|loc=Chapter §5 Item 30: Favor generic methods|pp=135-138}} इस प्रकार के चर को विधि के औपचारिक प्रकार के पैरामीटर के रूप में जाना जाता है। औपचारिक प्रकार पैरामीटर लिस्ट का रूप किसी वर्ग या इंटरफ़ेस के प्रकार पैरामीटर लिस्ट के समान है।
*विधि सामान्य है यदि यह एक या अधिक टाइप के चर घोषित करती है।{{sfn|Bloch|2018|loc=Chapter §5 Item 30: Favor generic methods|pp=135-138}} इस टाइप के चर को विधि के औपचारिक टाइप के पैरामीटर के रूप में जाना जाता है। औपचारिक टाइप पैरामीटर सूची का रूप किसी वर्ग या इंटरफ़ेस के टाइप पैरामीटर सूची के समान है।
*कंस्ट्रक्टर को जेनेरिक घोषित किया जा सकता है, चाहे कंस्ट्रक्टर को जिस वर्ग में घोषित किया गया है वह स्वयं जेनेरिक है या नहीं। कंस्ट्रक्टर सामान्य होता है यदि वह एक या अधिक प्रकार के वेरिएबल घोषित करता है। इन प्रकार के चर को कंस्ट्रक्टर के औपचारिक प्रकार के पैरामीटर के रूप में जाना जाता है। औपचारिक प्रकार पैरामीटर लिस्ट का रूप सामान्य वर्ग या इंटरफ़ेस की प्रकार पैरामीटर लिस्ट के समान है।
*कंस्ट्रक्टर को जेनेरिक घोषित किया जा सकता है, चाहे कंस्ट्रक्टर को जिस वर्ग में घोषित किया गया है वह स्वयं जेनेरिक है या नहीं। कंस्ट्रक्टर सामान्य होता है यदि वह एक या अधिक टाइप के वेरिएबल घोषित करता है। इन टाइप के चर को कंस्ट्रक्टर के औपचारिक टाइप के पैरामीटर के रूप में जाना जाता है। औपचारिक टाइप पैरामीटर सूची का रूप सामान्य वर्ग या इंटरफ़ेस की टाइप पैरामीटर सूची के समान है।


==प्रेरणा==
==प्रेरणा==
जावा कोड का निम्नलिखित ब्लॉक उस समस्या को दर्शाता है, जो जेनेरिक का उपयोग न करने पर उपलब्ध होती है। सबसे पहले, यह {{Javadoc:SE|name=Object|package=java.lang|java/lang|Object}} प्रकार की {{Javadoc:SE|name=ArrayList|package=java.util|java/util|ArrayList}} घोषित करता है। फिर, यह <code>ArrayList</code> में <code>String</code> जोड़ता है। अंत में, यह जोड़े गए <code>String</code> को पुनः प्राप्त करने का प्रयास करता है और इसे <code>Integer</code> में डालने का प्रयास करता है - लॉजिक में त्रुटि, क्योंकि सामान्यतः पूर्णांक में इच्छानुसार स्ट्रिंग डालना संभव नहीं है।
जावा कोड का निम्नलिखित ब्लॉक उस समस्या को दर्शाता है, जो जेनेरिक का उपयोग न करने पर उपलब्ध होती है। सबसे पहले, यह {{Javadoc:SE|name=Object|package=java.lang|java/lang|Object}} टाइप की {{Javadoc:SE|name=ArrayList|package=java.util|java/util|ArrayList}} घोषित करता है। फिर, यह <code>ArrayList</code> में <code>String</code> जोड़ता है। अंत में, यह जोड़े गए <code>String</code> को पुनः प्राप्त करने का प्रयास करता है और इसे <code>Integer</code> में डालने का प्रयास करता है - लॉजिक में त्रुटि, क्योंकि सामान्यतः पूर्णांक में इच्छानुसार स्ट्रिंग डालना संभव नहीं है।


<syntaxhighlight lang="Java">
<syntaxhighlight lang="Java">
Line 23: Line 23:
final Integer i = (Integer) v.get(0); // Run time error
final Integer i = (Integer) v.get(0); // Run time error
</syntaxhighlight>
</syntaxhighlight>
चूँकि कोड बिना किसी त्रुटि के संकलित किया गया है, यह कोड की तीसरी लाइन निष्पादित करते समय रनटाइम अपवाद (<code>java.lang.ClassCastException</code>) फेंकता है। जेनरिक का उपयोग करके संकलन समय के समय इस प्रकार की लॉजिक त्रुटि का पता लगाया जा सकता है{{sfn|Bloch|2018|loc=Chapter §5 Item 26: Don't use raw types|pp=117-122}} और उनका उपयोग करने के लिए प्राथमिक प्रेरणा है।{{sfn|Bloch|2018|loc=Chapter §5 Item 28: Prefer lists to arrays|pp=126-129}} यह एक या अधिक प्रकार के वेरिएबल को परिभाषित करता है, जो पैरामीटर के रूप में कार्य करते हैं।
चूँकि कोड बिना किसी त्रुटि के संकलित किया गया है, यह कोड की तीसरी लाइन निष्पादित करते समय रनटाइम अपवाद (<code>java.lang.ClassCastException</code>) फेंकता है। जेनरिक का उपयोग करके संकलन समय के समय इस टाइप की लॉजिक त्रुटि का पता लगाया जा सकता है{{sfn|Bloch|2018|loc=Chapter §5 Item 26: Don't use raw types|pp=117-122}} और उनका उपयोग करने के लिए प्राथमिक प्रेरणा है।{{sfn|Bloch|2018|loc=Chapter §5 Item 28: Prefer lists to arrays|pp=126-129}} यह एक या अधिक टाइप के वेरिएबल को परिभाषित करता है, जो पैरामीटर के रूप में कार्य करते हैं।


उपरोक्त कोड खंड को जेनेरिक का उपयोग करके निम्नानुसार फिर से लिखा जा सकता है:
उपरोक्त कोड खंड को जेनेरिक का उपयोग करके निम्नानुसार फिर से लिखा जा सकता है:
Line 32: Line 32:
final Integer i = (Integer) v.get(0); // (type error)  compilation-time error
final Integer i = (Integer) v.get(0); // (type error)  compilation-time error
</syntaxhighlight>
</syntaxhighlight>
कोण कोष्ठक के अन्दर टाइप पैरामीटर <code>String</code> <code>ArrayList</code> को <code>String</code> (<code>ArrayList</code> के सामान्य <code>Object</code> घटकों का वंशज) से गठित होने की घोषणा करता है। जेनेरिक के साथ, तीसरी लाइन को किसी विशेष प्रकार में डालना अब आवश्यक नहीं है, क्योंकि <code>v.get(0)</code> के परिणाम को कंपाइलर द्वारा उत्पन्न कोड द्वारा <code>String</code> के रूप में परिभाषित किया गया है।
कोण कोष्ठक के अन्दर टाइप पैरामीटर <code>String</code> <code>ArrayList</code> को <code>String</code> (<code>ArrayList</code> के सामान्य <code>Object</code> घटकों का वंशज) से गठित होने की घोषणा करता है। जेनेरिक के साथ, तीसरी लाइन को किसी विशेष टाइप में डालना अब आवश्यक नहीं है, क्योंकि <code>v.get(0)</code> के परिणाम को कंपाइलर द्वारा उत्पन्न कोड द्वारा <code>String</code> के रूप में परिभाषित किया गया है।


इस खंड की तीसरी लाइन में तार्किक दोष को संकलन-समय त्रुटि (J2SE 5.0 या बाद के संस्करण के साथ) के रूप में पहचाना जाएगा क्योंकि कंपाइलर यह पता लगाएगा कि <code>v.get(0)</code> <code>Integer</code> पूर्णांक के अतिरिक्त <code>String</code> लौटाता है।{{sfn|Bloch|2018|loc=Chapter §5 Item 26: Don't use raw types|pp=117-122}} अधिक विस्तृत उदाहरण के लिए, संदर्भ देखें।<ref>{{cite web |url=http://www.oracle.com/technetwork/java/javase/generics-tutorial-159168.pdf |title=जावा प्रोग्रामिंग भाषा में जेनेरिक|author=Gilad Bracha |date=July 5, 2004 |website=www.oracle.com}}</ref>
इस खंड की तीसरी लाइन में तार्किक दोष को संकलन-समय त्रुटि (J2SE 5.0 या बाद के संस्करण के साथ) के रूप में पहचाना जाएगा क्योंकि कंपाइलर यह पता लगाएगा कि <code>v.get(0)</code> <code>Integer</code> पूर्णांक के अतिरिक्त <code>String</code> लौटाता है।{{sfn|Bloch|2018|loc=Chapter §5 Item 26: Don't use raw types|pp=117-122}} अधिक विस्तृत उदाहरण के लिए, संदर्भ देखें।<ref>{{cite web |url=http://www.oracle.com/technetwork/java/javase/generics-tutorial-159168.pdf |title=जावा प्रोग्रामिंग भाषा में जेनेरिक|author=Gilad Bracha |date=July 5, 2004 |website=www.oracle.com}}</ref>
Line 112: Line 112:
}
}
</syntaxhighlight>
</syntaxhighlight>
नोट: यदि हम पहले <code><Type></code> को हटा दें, उपरोक्त विधि में, हमें संकलन त्रुटि मिलेगी (प्रतीक प्रकार नहीं मिल सका), क्योंकि यह प्रतीक की घोषणा का प्रतिनिधित्व करता है।
नोट: यदि हम पहले <code><Type></code> को हटा दें, उपरोक्त विधि में, हमें संकलन त्रुटि मिलेगी (प्रतीक टाइप नहीं मिल सका), क्योंकि यह प्रतीक की घोषणा का प्रतिनिधित्व करता है।


कई स्थितियों में, विधि के उपयोगकर्ता को प्रकार के पैरामीटर को इंगित करने की आवश्यकता नहीं होती है, क्योंकि उनका अनुमान लगाया जा सकता है:
कई स्थितियों में, विधि के उपयोगकर्ता को टाइप के पैरामीटर को इंगित करने की आवश्यकता नहीं होती है, क्योंकि उनका अनुमान लगाया जा सकता है:


<syntaxhighlight lang="Java">
<syntaxhighlight lang="Java">
Line 124: Line 124:
final Entry<String, String> pair = Entry.<String>twice("Hello");
final Entry<String, String> pair = Entry.<String>twice("Hello");
</syntaxhighlight>
</syntaxhighlight>
[[आदिम प्रकार]] के उपयोग की अनुमति नहीं है, और इसके अतिरिक्त ऑब्जेक्ट प्रकार (ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग) बॉक्सिंग संस्करणों का उपयोग किया जाना चाहिए:
[[आदिम प्रकार|आदिम टाइप]] के उपयोग की अनुमति नहीं है, और इसके अतिरिक्त ऑब्जेक्ट टाइप (ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग) बॉक्सिंग संस्करणों का उपयोग किया जाना चाहिए:


<syntaxhighlight lang="Java">
<syntaxhighlight lang="Java">
Line 136: Line 136:
}
}
</syntaxhighlight>
</syntaxhighlight>
ऐसी स्थितियों में आप आदिम प्रकारों का भी उपयोग नहीं कर सकते, उदाहरण के लिए:
ऐसी स्थितियों में आप आदिम टाइपों का भी उपयोग नहीं कर सकते, उदाहरण के लिए:


<syntaxhighlight lang="Java">
<syntaxhighlight lang="Java">
Line 144: Line 144:


==डायमंड ऑपरेटर==
==डायमंड ऑपरेटर==
प्रकार के अनुमान के लिए धन्यवाद, जावा एसई 7 और इसके बाद के संस्करण प्रोग्रामर को कोण कोष्ठक की खाली जोड़ी (<code>&lt;&gt;</code>, जिसे डायमंड ऑपरेटर कहा जाता है) को कोण कोष्ठक की जोड़ी के लिए प्रतिस्थापित करने की अनुमति देता है जिसमें एक या अधिक प्रकार के पैरामीटर होते हैं जो पर्याप्त रूप से बंद संदर्भ का तात्पर्य है।<ref>{{cite web | url=http://docs.oracle.com/javase/7/docs/technotes/guides/language/type-inference-generic-instance-creation.html | title=Type Inference for Generic Instance Creation }}</ref> इस प्रकार, <code>Entry</code> का उपयोग करके उपरोक्त कोड उदाहरण को इस प्रकार पुनः लिखा जा सकता है:
टाइप के अनुमान के लिए धन्यवाद, जावा एसई 7 और इसके बाद के संस्करण प्रोग्रामर को कोण कोष्ठक की खाली जोड़ी (<code>&lt;&gt;</code>, जिसे डायमंड ऑपरेटर कहा जाता है) को कोण कोष्ठक की जोड़ी के लिए प्रतिस्थापित करने की अनुमति देता है जिसमें एक या अधिक टाइप के पैरामीटर होते हैं जो पर्याप्त रूप से बंद संदर्भ का तात्पर्य है।<ref>{{cite web | url=http://docs.oracle.com/javase/7/docs/technotes/guides/language/type-inference-generic-instance-creation.html | title=Type Inference for Generic Instance Creation }}</ref> इस टाइप, <code>Entry</code> का उपयोग करके उपरोक्त कोड उदाहरण को इस टाइप पुनः लिखा जा सकता है:


<syntaxhighlight lang="Java">
<syntaxhighlight lang="Java">
Line 161: Line 161:
{{main|वाइल्डकार्ड (जावा)}}
{{main|वाइल्डकार्ड (जावा)}}


पैरामीटरयुक्त प्रकार के लिए एक प्रकार का लॉजिक किसी ठोस वर्ग या इंटरफ़ेस तक सीमित नहीं है। जावा पैरामीटरयुक्त प्रकारों के लिए प्रकार के लॉजिक के रूप में "टाइप वाइल्डकार्ड" के उपयोग की अनुमति देता है। वाइल्डकार्ड "<code><?></code>" रूप में प्रकार के लॉजिक हैं; वैकल्पिक रूप से ऊपरी या निचली सीमा के साथ। यह देखते हुए कि वाइल्डकार्ड द्वारा दर्शाया गया स्पष्ट प्रकार अज्ञात है, उन विधियों के प्रकार पर प्रतिबंध लगाए जाते हैं जिन्हें किसी ऑब्जेक्ट पर बुलाया जा सकता है जो पैरामीटरयुक्त प्रकारों का उपयोग करता है।
पैरामीटरयुक्त टाइप के लिए एक टाइप का लॉजिक किसी ठोस वर्ग या इंटरफ़ेस तक सीमित नहीं है। जावा पैरामीटरयुक्त टाइपों के लिए टाइप के लॉजिक के रूप में "टाइप वाइल्डकार्ड" के उपयोग की अनुमति देता है। वाइल्डकार्ड "<code><?></code>" रूप में टाइप के लॉजिक हैं; वैकल्पिक रूप से ऊपरी या निचली सीमा के साथ। यह देखते हुए कि वाइल्डकार्ड द्वारा दर्शाया गया स्पष्ट टाइप अज्ञात है, उन विधियों के टाइप पर प्रतिबंध लगाए जाते हैं जिन्हें किसी ऑब्जेक्ट पर बुलाया जा सकता है जो पैरामीटरयुक्त टाइपों का उपयोग करता है।


यहां उदाहरण दिया गया है, जहां <code>Collection<E></code> के तत्व प्रकार को वाइल्डकार्ड द्वारा पैरामीटराइज़ किया गया है:
यहां उदाहरण दिया गया है, जहां <code>Collection<E></code> के तत्व टाइप को वाइल्डकार्ड द्वारा पैरामीटराइज़ किया गया है:


<syntaxhighlight lang="java">
<syntaxhighlight lang="java">
Line 169: Line 169:
c.add(new Object()); // compile-time error
c.add(new Object()); // compile-time error
c.add(null); // allowed</syntaxhighlight>
c.add(null); // allowed</syntaxhighlight>
चूँकि हम नहीं जानते कि तत्व प्रकार <code>c</code> का क्या अर्थ है, हम इसमें ऑब्जेक्ट नहीं जोड़ सकते। <code>add()</code> विधि <code>E</code> e> प्रकार के लॉजिक लेती है, जो कि <code>Collection<E></code> जेनेरिक इंटरफ़ेस का तत्व प्रकार है। जब वास्तविक प्रकार का लॉजिक <code>?</code> होता है, तो यह किसी अज्ञात प्रकार का प्रतिनिधित्व करता है। <code>add()</code> विधि में हम जो भी विधि लॉजिक मान पास करते हैं वह इस अज्ञात प्रकार का उपप्रकार होना चाहिए। चूँकि हम नहीं जानते कि वह किस प्रकार का है, हम कुछ भी पारित नहीं कर सकते हैं। एकमात्र अपवाद शून्य है; जो हर प्रकार का सदस्य है।<ref>{{cite web |url=http://www.oracle.com/technetwork/java/javase/generics-tutorial-159168.pdf |title=जावा प्रोग्रामिंग भाषा में जेनेरिक|author=Gilad Bracha |date=July 5, 2004 |pages=5 |website=www.oracle.com}}</ref>
चूँकि हम नहीं जानते कि तत्व टाइप <code>c</code> का क्या अर्थ है, हम इसमें ऑब्जेक्ट नहीं जोड़ सकते। <code>add()</code> विधि <code>E</code> e> टाइप के लॉजिक लेती है, जो कि <code>Collection<E></code> जेनेरिक इंटरफ़ेस का तत्व टाइप है। जब वास्तविक टाइप का लॉजिक <code>?</code> होता है, तो यह किसी अज्ञात टाइप का प्रतिनिधित्व करता है। <code>add()</code> विधि में हम जो भी विधि लॉजिक मान पास करते हैं वह इस अज्ञात टाइप का उपटाइप होना चाहिए। चूँकि हम नहीं जानते कि वह किस टाइप का है, हम कुछ भी पारित नहीं कर सकते हैं। एकमात्र अपवाद शून्य है; जो हर टाइप का सदस्य है।<ref>{{cite web |url=http://www.oracle.com/technetwork/java/javase/generics-tutorial-159168.pdf |title=जावा प्रोग्रामिंग भाषा में जेनेरिक|author=Gilad Bracha |date=July 5, 2004 |pages=5 |website=www.oracle.com}}</ref>


किसी प्रकार के वाइल्डकार्ड की ऊपरी सीमा को निर्दिष्ट करने के लिए, {{java|extends}} कीवर्ड का उपयोग यह इंगित करने के लिए किया जाता है कि प्रकार लॉजिक बाउंडिंग क्लास का उपप्रकार है।{{sfn|Bloch|2018|loc=Chapter §5 Item 31: Use bounded wildcards to increase API flexibility|pp=139-145}} तो {{java|List<? extends Number>}} का अर्थ है कि दी गई लिस्ट में कुछ अज्ञात प्रकार की वस्तुएं हैं जो <code>Number</code> वर्ग का विस्तार करती हैं। उदाहरण के लिए, लिस्ट <code>List&lt;Float&gt;</code> या <code>List&lt;Number&gt;</code> हो सकती है। लिस्ट से किसी तत्व को पढ़ने पर <code>Number</code> वापस आ जाएगी। फिर से, अशक्त तत्वों को जोड़ने की भी अनुमति है।<ref>{{Cite web |url=https://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html |title=Wildcards > Bonus > Generics |last=Bracha |first=Gilad |author-link=Gilad Bracha |publisher=Oracle |website=The Java™ Tutorials |quote=...The sole exception is null, which is a member of every type...}}</ref>
किसी टाइप के वाइल्डकार्ड की ऊपरी सीमा को निर्दिष्ट करने के लिए, {{java|extends}} कीवर्ड का उपयोग यह इंगित करने के लिए किया जाता है कि टाइप लॉजिक बाउंडिंग क्लास का उपटाइप है।{{sfn|Bloch|2018|loc=Chapter §5 Item 31: Use bounded wildcards to increase API flexibility|pp=139-145}} तो {{java|List<? extends Number>}} का अर्थ है कि दी गई सूची में कुछ अज्ञात टाइप की वस्तुएं हैं जो <code>Number</code> वर्ग का विस्तार करती हैं। उदाहरण के लिए, सूची <code>List&lt;Float&gt;</code> या <code>List&lt;Number&gt;</code> हो सकती है। सूची से किसी तत्व को पढ़ने पर <code>Number</code> वापस आ जाएगी। फिर से, अशक्त तत्वों को जोड़ने की भी अनुमति है।<ref>{{Cite web |url=https://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html |title=Wildcards > Bonus > Generics |last=Bracha |first=Gilad |author-link=Gilad Bracha |publisher=Oracle |website=The Java™ Tutorials |quote=...The sole exception is null, which is a member of every type...}}</ref>


उपरोक्त वाइल्डकार्ड का उपयोग लचीलापन जोड़ता है{{sfn|Bloch|2018|loc=Chapter §5 Item 31: Use bounded wildcards to increase API flexibility|pp=139-145}} क्योंकि ठोस प्रकार के लॉजिक के साथ किन्हीं दो पैरामीटरयुक्त प्रकारों के बीच कोई विरासत संबंध नहीं है। न तो <code>List<Number></code> और न ही <code>List<Integer></code> दूसरे का उपप्रकार है; तथापि <code>Integer</code> <code>Number</code> का उपप्रकार है।{{sfn|Bloch|2018|loc=Chapter §5 Item 31: Use bounded wildcards to increase API flexibility|pp=139-145}} इसलिए, कोई भी विधि जो <code>List<Number></code> को पैरामीटर के रूप में लेती है, <code>List<Integer></code> के लॉजिक को स्वीकार नहीं करती है। यदि ऐसा होता, तो इसमें ऐसा <code>Number</code> सम्मिलित करना संभव होता जो <code>Integer</code> नहीं है; जो प्रकार की सुरक्षा का उल्लंघन करता है। यहां उदाहरण दिया गया है जो दर्शाता है कि यदि <code>List<Integer></code> <code>List<Number></code> का उपप्रकार होता तो किस प्रकार प्रकार की सुरक्षा का उल्लंघन किया जाता:
उपरोक्त वाइल्डकार्ड का उपयोग लचीलापन जोड़ता है{{sfn|Bloch|2018|loc=Chapter §5 Item 31: Use bounded wildcards to increase API flexibility|pp=139-145}} क्योंकि ठोस टाइप के लॉजिक के साथ किन्हीं दो पैरामीटरयुक्त टाइपों के बीच कोई विरासत संबंध नहीं है। न तो <code>List<Number></code> और न ही <code>List<Integer></code> दूसरे का उपटाइप है; तथापि <code>Integer</code> <code>Number</code> का उपटाइप है।{{sfn|Bloch|2018|loc=Chapter §5 Item 31: Use bounded wildcards to increase API flexibility|pp=139-145}} इसलिए, कोई भी विधि जो <code>List<Number></code> को पैरामीटर के रूप में लेती है, <code>List<Integer></code> के लॉजिक को स्वीकार नहीं करती है। यदि ऐसा होता, तो इसमें ऐसा <code>Number</code> सम्मिलित करना संभव होता जो <code>Integer</code> नहीं है; जो टाइप की सुरक्षा का उल्लंघन करता है। यहां उदाहरण दिया गया है जो दर्शाता है कि यदि <code>List<Integer></code> <code>List<Number></code> का उपटाइप होता तो किस टाइप टाइप की सुरक्षा का उल्लंघन किया जाता:


<syntaxhighlight lang="java">
<syntaxhighlight lang="java">
Line 182: Line 182:
final Integer x = ints.get(1); // now 3.14 is assigned to an Integer variable!
final Integer x = ints.get(1); // now 3.14 is assigned to an Integer variable!
</syntaxhighlight>
</syntaxhighlight>
वाइल्डकार्ड के साथ समाधान काम करता है क्योंकि यह उन परिचालनों की अनुमति नहीं देता है जो प्रकार की सुरक्षा का उल्लंघन करेंगे:
वाइल्डकार्ड के साथ समाधान काम करता है क्योंकि यह उन परिचालनों की अनुमति नहीं देता है जो टाइप की सुरक्षा का उल्लंघन करेंगे:


<syntaxhighlight lang="java">
<syntaxhighlight lang="java">
Line 189: Line 189:
nums.add(null); // allowed   
nums.add(null); // allowed   
</syntaxhighlight>
</syntaxhighlight>
किसी प्रकार के वाइल्डकार्ड के निचले बाउंडिंग वर्ग को निर्दिष्ट करने के लिए, <code>super</code> कीवर्ड का प्रयोग किया जाता है। यह कीवर्ड इंगित करता है कि प्रकार लॉजिक बाउंडिंग क्लास का सुपरटाइप है। इसलिए, <code>List&lt;Number&gt;</code> या <code>List&lt;Object&gt;</code> {{java|List<? super Number>}} का प्रतिनिधित्व कर सकता है। {{java|List<?}} के रूप में परिभाषित लिस्ट से पढ़ना <code>super Number></code> <code>Object</code> प्रकार के तत्व लौटाता है। ऐसी लिस्ट में जोड़ने के लिए या तो <code>Number</code> प्रकार के तत्वों, <code>Number</code> के किसी उपप्रकार या शून्य (जो हर प्रकार का सदस्य है) की आवश्यकता होती है।
किसी टाइप के वाइल्डकार्ड के निचले बाउंडिंग वर्ग को निर्दिष्ट करने के लिए, <code>super</code> कीवर्ड का प्रयोग किया जाता है। यह कीवर्ड इंगित करता है कि टाइप लॉजिक बाउंडिंग क्लास का सुपरटाइप है। इसलिए, <code>List&lt;Number&gt;</code> या <code>List&lt;Object&gt;</code> {{java|List<? super Number>}} का प्रतिनिधित्व कर सकता है। {{java|List<?}} के रूप में परिभाषित सूची से पढ़ना <code>super Number></code> <code>Object</code> टाइप के तत्व लौटाता है। ऐसी सूची में जोड़ने के लिए या तो <code>Number</code> टाइप के तत्वों, <code>Number</code> के किसी उपटाइप या शून्य (जो हर टाइप का सदस्य है) की आवश्यकता होती है।


[[जोशुआ बलोच]] की पुस्तक इफेक्टिव जावा से स्मरणीय पीईसीएस (निर्माता एक्सटेंड्स, कंज्यूमर सुपर) यह याद रखने की आसान विधि देती है कि जब जावा में वाइल्डकार्ड (सहप्रसरण और विरोधाभास के अनुरूप) का उपयोग करना है।{{sfn|Bloch|2018|loc=Chapter §5 Item 31: Use bounded wildcards to increase API flexibility|pp=139-145}}
[[जोशुआ बलोच]] की पुस्तक इफेक्टिव जावा से स्मरणीय पीईसीएस (निर्माता एक्सटेंड्स, कंज्यूमर सुपर) यह याद रखने की आसान विधि देती है कि जब जावा में वाइल्डकार्ड (सहप्रसरण और विरोधाभास के अनुरूप) का उपयोग करना है।{{sfn|Bloch|2018|loc=Chapter §5 Item 31: Use bounded wildcards to increase API flexibility|pp=139-145}}
Line 205: Line 205:




==प्रकार मिटाने की समस्या==
==टाइप मिटाने की समस्या==
टाइप-शुद्धता के लिए संकलन-समय पर जेनेरिक की जाँच की जाती है।{{sfn|Bloch|2018|loc=Chapter §5 Item 26: Don't use raw types|pp=117-122}} सामान्य प्रकार की जानकारी को [[प्रकार मिटाना]] नामक प्रक्रिया में हटा दिया जाता है।{{sfn|Bloch|2018|loc=Chapter §5 Item 28: Prefer lists to arrays|pp=126-129}} उदाहरण के लिए, <code>List&lt;Integer&gt;</code> गैर-जेनेरिक <code>List</code>प्रकार में परिवर्तित कर दिया जाएगा, जिसमें सामान्यतः इच्छानुसार वस्तुएं सम्मिलित होती हैं। संकलन-समय जांच यह गारंटी देती है कि परिणामी कोड सही प्रकार का उपयोग करता है।{{sfn|Bloch|2018|loc=Chapter §5 Item 26: Don't use raw types|pp=117-122}}
टाइप-शुद्धता के लिए संकलन-समय पर जेनेरिक की जाँच की जाती है।{{sfn|Bloch|2018|loc=Chapter §5 Item 26: Don't use raw types|pp=117-122}} सामान्य टाइप की जानकारी को [[प्रकार मिटाना|टाइप मिटाना]] नामक प्रक्रिया में हटा दिया जाता है।{{sfn|Bloch|2018|loc=Chapter §5 Item 28: Prefer lists to arrays|pp=126-129}} उदाहरण के लिए, <code>List&lt;Integer&gt;</code> गैर-जेनेरिक <code>List</code>टाइप में परिवर्तित कर दिया जाएगा, जिसमें सामान्यतः इच्छानुसार वस्तुएं सम्मिलित होती हैं। संकलन-समय जांच यह गारंटी देती है कि परिणामी कोड सही टाइप का उपयोग करता है।{{sfn|Bloch|2018|loc=Chapter §5 Item 26: Don't use raw types|pp=117-122}}


प्रकार के क्षरण के कारण, रन-टाइम पर प्रकार के पैरामीटर निर्धारित नहीं किए जा सकते।{{sfn|Bloch|2018|loc=Chapter §5 Item 28: Prefer lists to arrays|pp=126-129}} उदाहरण के लिए, जब रनटाइम पर <code>ArrayList</code> की जांच की जाती है, तो यह निर्धारित करने का कोई सामान्य विधि नहीं है कि, प्रकार मिटाने से पहले, यह <code>ArrayList&lt;Integer&gt;</code> था या <code>ArrayList&lt;Float&gt;</code> था। कई लोग इस प्रतिबंध से असंतुष्ट हैं।<ref>{{cite web|first=Neal|last=Gafter|title=जावा के लिए परिष्कृत जेनेरिक|date=2006-11-05|access-date=2010-04-20|url=http://gafter.blogspot.ro/2006/11/reified-generics-for-java.html}}</ref> यह आंशिक दृष्टिकोण हैं। उदाहरण के लिए, व्यक्तिगत तत्वों की जांच यह निर्धारित करने के लिए की जा सकती है कि वे किस प्रकार के हैं; उदाहरण के लिए, यदि किसी <code>ArrayList</code> में <code>Integer</code> है, तो उस <code>ArrayList</code> को <code>Integer</code> के साथ पैरामीटराइज़ किया गया हो सकता है (चूँकि, इसे <code>Integer</code> के किसी भी पैरेंट, जैसे <code>Number</code> या <code>Object</code>) के साथ पैरामीटराइज़ किया गया हो सकता है।
टाइप के क्षरण के कारण, रन-टाइम पर टाइप के पैरामीटर निर्धारित नहीं किए जा सकते।{{sfn|Bloch|2018|loc=Chapter §5 Item 28: Prefer lists to arrays|pp=126-129}} उदाहरण के लिए, जब रनटाइम पर <code>ArrayList</code> की जांच की जाती है, तो यह निर्धारित करने का कोई सामान्य विधि नहीं है कि, टाइप मिटाने से पहले, यह <code>ArrayList&lt;Integer&gt;</code> था या <code>ArrayList&lt;Float&gt;</code> था। कई लोग इस प्रतिबंध से असंतुष्ट हैं।<ref>{{cite web|first=Neal|last=Gafter|title=जावा के लिए परिष्कृत जेनेरिक|date=2006-11-05|access-date=2010-04-20|url=http://gafter.blogspot.ro/2006/11/reified-generics-for-java.html}}</ref> यह आंशिक दृष्टिकोण हैं। उदाहरण के लिए, व्यक्तिगत तत्वों की जांच यह निर्धारित करने के लिए की जा सकती है कि वे किस टाइप के हैं; उदाहरण के लिए, यदि किसी <code>ArrayList</code> में <code>Integer</code> है, तो उस <code>ArrayList</code> को <code>Integer</code> के साथ पैरामीटराइज़ किया गया हो सकता है (चूँकि, इसे <code>Integer</code> के किसी भी पैरेंट, जैसे <code>Number</code> या <code>Object</code>) के साथ पैरामीटराइज़ किया गया हो सकता है।


इस बिंदु को प्रदर्शित करते हुए, निम्नलिखित कोड समान आउटपुट देता है:
इस बिंदु को प्रदर्शित करते हुए, निम्नलिखित कोड समान आउटपुट देता है:
Line 218: Line 218:
}
}
</syntaxhighlight>
</syntaxhighlight>
प्रकार के क्षरण का अन्य प्रभाव यह है कि सामान्य वर्ग किसी भी तरह से, प्रत्यक्ष या अप्रत्यक्ष रूप से, <code>Throwable</code> वर्ग का विस्तार नहीं कर सकता है:<ref>{{cite web|url=http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.1.2|title=Java Language Specification, Section 8.1.2|publisher=Oracle|access-date=24 October 2015}}</ref>
टाइप के क्षरण का अन्य प्रभाव यह है कि सामान्य वर्ग किसी भी तरह से, प्रत्यक्ष या अप्रत्यक्ष रूप से, <code>Throwable</code> वर्ग का विस्तार नहीं कर सकता है:<ref>{{cite web|url=http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.1.2|title=Java Language Specification, Section 8.1.2|publisher=Oracle|access-date=24 October 2015}}</ref>


<syntaxhighlight lang="java">
<syntaxhighlight lang="java">
public class GenericException<T> extends Exception
public class GenericException<T> extends Exception
</syntaxhighlight>
</syntaxhighlight>
इसके समर्थित न होने का कारण प्रकार का क्षरण है:
इसके समर्थित न होने का कारण टाइप का क्षरण है:
<syntaxhighlight lang="java">
<syntaxhighlight lang="java">
try {
try {
Line 237: Line 237:
टाइप इरेज़र के कारण, रनटाइम को पता नहीं चलेगा कि कौन सा कैच ब्लॉक निष्पादित करना है, इसलिए यह कंपाइलर द्वारा निषिद्ध है।
टाइप इरेज़र के कारण, रनटाइम को पता नहीं चलेगा कि कौन सा कैच ब्लॉक निष्पादित करना है, इसलिए यह कंपाइलर द्वारा निषिद्ध है।


जावा जेनेरिक [[सी++ टेम्पलेट्स]] से भिन्न हैं। उपयोग किए गए पैरामीटर प्रकारों की संख्या की परवाह किए बिना, जावा जेनेरिक जेनेरिक वर्ग या फलन का केवल संकलित संस्करण उत्पन्न करते हैं। इसके अतिरिक्त, जावा रन-टाइम वातावरण को यह जानने की आवश्यकता नहीं है कि किस पैरामीटरयुक्त प्रकार का उपयोग किया जाता है क्योंकि प्रकार की जानकारी संकलन-समय पर मान्य होती है और संकलित कोड में सम्मिलित नहीं होती है। परिणामस्वरूप, पैरामीटरयुक्त प्रकार के जावा क्लास को इंस्टेंट करना असंभव है क्योंकि इंस्टेंटेशन के लिए कंस्ट्रक्टर को कॉल की आवश्यकता होती है, जो कि प्रकार अज्ञात होने पर अनुपलब्ध है।
जावा जेनेरिक [[सी++ टेम्पलेट्स]] से भिन्न हैं। उपयोग किए गए पैरामीटर टाइपों की संख्या की परवाह किए बिना, जावा जेनेरिक जेनेरिक वर्ग या फलन का केवल संकलित संस्करण उत्पन्न करते हैं। इसके अतिरिक्त, जावा रन-टाइम वातावरण को यह जानने की आवश्यकता नहीं है कि किस पैरामीटरयुक्त टाइप का उपयोग किया जाता है क्योंकि टाइप की जानकारी संकलन-समय पर मान्य होती है और संकलित कोड में सम्मिलित नहीं होती है। परिणामस्वरूप, पैरामीटरयुक्त टाइप के जावा क्लास को इंस्टेंट करना असंभव है क्योंकि इंस्टेंटेशन के लिए कंस्ट्रक्टर को कॉल की आवश्यकता होती है, जो कि टाइप अज्ञात होने पर अनुपलब्ध है।


उदाहरण के लिए, निम्नलिखित कोड संकलित नहीं किया जा सकता:
उदाहरण के लिए, निम्नलिखित कोड संकलित नहीं किया जा सकता:
Line 245: Line 245:
}
}
</syntaxhighlight>
</syntaxhighlight>
चूँकि रनटाइम पर प्रति जेनेरिक क्लास की केवल प्रतिलिपि होती है, [[स्थैतिक चर]] को क्लास के सभी उदाहरणों के बीच साझा किया जाता है, चाहे उनके प्रकार के पैरामीटर कुछ भी हों। परिणामस्वरूप, प्रकार पैरामीटर का उपयोग स्थिर चर की घोषणा में या स्थिर विधियों में नहीं किया जा सकता है।
चूँकि रनटाइम पर प्रति जेनेरिक क्लास की केवल प्रतिलिपि होती है, [[स्थैतिक चर]] को क्लास के सभी उदाहरणों के बीच साझा किया जाता है, चाहे उनके टाइप के पैरामीटर कुछ भी हों। परिणामस्वरूप, टाइप पैरामीटर का उपयोग स्थिर चर की घोषणा में या स्थिर विधियों में नहीं किया जा सकता है।


जावा SE5 से पहले लिखे गए प्रोग्रामों के साथ बैकवर्ड संगतता बनाए रखने के लिए जावा में टाइप इरेज़र प्रयुक्त किया गया था।{{sfn|Bloch|2018|loc=Chapter §5 Item 26: Don't use raw types|pp=117-122}}
जावा SE5 से पहले लिखे गए प्रोग्रामों के साथ बैकवर्ड संगतता बनाए रखने के लिए जावा में टाइप इरेज़र प्रयुक्त किया गया था।{{sfn|Bloch|2018|loc=Chapter §5 Item 26: Don't use raw types|pp=117-122}}
Line 251: Line 251:
==सरणी से अंतर ==
==सरणी से अंतर ==


जावा में सरणियों (आदिम सरणियों और {{code|Object}} सरणियों दोनों) और जेनेरिक के बीच कई महत्वपूर्ण अंतर हैं। दो प्रमुख अंतर, अर्थात् [[वेरिएंस (कंप्यूटर विज्ञान)|विचरण]] और [[रीफिकेशन (कंप्यूटर विज्ञान)|रीफिकेशन]] के संदर्भ में अंतर।
जावा में ऐरे (आदिम ऐरे और {{code|Object}} ऐरे दोनों) और जेनेरिक के बीच कई महत्वपूर्ण अंतर हैं। दो प्रमुख अंतर, अर्थात् [[वेरिएंस (कंप्यूटर विज्ञान)|विचरण]] और [[रीफिकेशन (कंप्यूटर विज्ञान)|रीफिकेशन]] के संदर्भ में अंतर।


=== सहप्रसरण, प्रतिप्रसरण और अपरिवर्तन ===
=== सहप्रसरण, प्रतिप्रसरण और अपरिवर्तन ===


{{main article|सहप्रसरण और प्रतिप्रसरण (कंप्यूटर विज्ञान)}}
{{main article|सहप्रसरण और प्रतिप्रसरण (कंप्यूटर विज्ञान)}}
जेनेरिक अपरिवर्तनीय हैं, जबकि सरणियाँ सहप्रसरण और प्रतिप्रसरण (कंप्यूटर विज्ञान) हैं।{{sfn|Bloch|2018|loc=Chapter §5 Item 28: Prefer lists to arrays|pp=126-129}} सरणियों जैसी गैर-जेनेरिक वस्तुओं की तुलना में जेनेरिक का उपयोग करने का यह लाभ है।{{sfn|Bloch|2018|loc=Chapter §5 Item 28: Prefer lists to arrays|pp=126-129}} विशेष रूप से, जेनरिक डेवलपर को कोड को ठीक करने के लिए विवश करने के लिए संकलन-समय अपवाद फेंककर रन टाइम अपवादों को रोकने में सहायता कर सकता है।
जेनेरिक अपरिवर्तनीय हैं, जबकि सरणियाँ सहप्रसरण और प्रतिप्रसरण (कंप्यूटर विज्ञान) हैं।{{sfn|Bloch|2018|loc=Chapter §5 Item 28: Prefer lists to arrays|pp=126-129}} ऐरे जैसी गैर-जेनेरिक वस्तुओं की तुलना में जेनेरिक का उपयोग करने का यह लाभ है।{{sfn|Bloch|2018|loc=Chapter §5 Item 28: Prefer lists to arrays|pp=126-129}} विशेष रूप से, जेनरिक डेवलपर को कोड को ठीक करने के लिए विवश करने के लिए संकलन-समय अपवाद फेंककर रन टाइम अपवादों को रोकने में सहायता कर सकता है।


उदाहरण के लिए, यदि कोई डेवलपर {{code|Object[]}} ऑब्जेक्ट घोषित करता है और ऑब्जेक्ट को नए {{code|Long[]}}] ऑब्जेक्ट के रूप में इंस्टेंट करता है, तो कोई संकलन-समय अपवाद नहीं फेंका जाता है (क्योंकि एरे सहसंयोजक होते हैं)।{{sfn|Bloch|2018|loc=Chapter §5 Item 28: Prefer lists to arrays|pp=126-129}} इससे यह ग़लत धारणा बन सकती है कि कोड सही ढंग से लिखा गया है। चूँकि, यदि डेवलपर इस {{code|Long[]}} ऑब्जेक्ट में {{code|String}} जोड़ने का प्रयास करता है, तो प्रोग्राम {{code|ArrayStoreException}} फेंक देगा।{{sfn|Bloch|2018|loc=Chapter §5 Item 28: Prefer lists to arrays|pp=126-129}} यदि डेवलपर जेनेरिक का उपयोग करता है तो इस रन-टाइम अपवाद से पूरी तरह बचा जा सकता है।
उदाहरण के लिए, यदि कोई डेवलपर {{code|Object[]}} ऑब्जेक्ट घोषित करता है और ऑब्जेक्ट को नए {{code|Long[]}}] ऑब्जेक्ट के रूप में इंस्टेंट करता है, तो कोई संकलन-समय अपवाद नहीं फेंका जाता है (क्योंकि एरे सहसंयोजक होते हैं)।{{sfn|Bloch|2018|loc=Chapter §5 Item 28: Prefer lists to arrays|pp=126-129}} इससे यह ग़लत धारणा बन सकती है कि कोड सही ढंग से लिखा गया है। चूँकि, यदि डेवलपर इस {{code|Long[]}} ऑब्जेक्ट में {{code|String}} जोड़ने का प्रयास करता है, तो प्रोग्राम {{code|ArrayStoreException}} फेंक देगा।{{sfn|Bloch|2018|loc=Chapter §5 Item 28: Prefer lists to arrays|pp=126-129}} यदि डेवलपर जेनेरिक का उपयोग करता है तो इस रन-टाइम अपवाद से पूरी तरह बचा जा सकता है।


यदि डेवलपर {{code|Collection<Object>}} ऑब्जेक्ट घोषित करता है और रिटर्न प्रकार {{code|ArrayList<Long>}} के साथ इस ऑब्जेक्ट का नया उदाहरण बनाता है, तो जावा कंपाइलर (सही ढंग से) असंगत प्रकारों की उपस्थिति को इंगित करने के लिए संकलन-समय अपवाद फेंक देगा (क्योंकि जेनेरिक हैं)।{{sfn|Bloch|2018|loc=Chapter §5 Item 28: Prefer lists to arrays|pp=126-129}} इसलिए, यह संभावित रन-टाइम अपवादों से बचा जाता है। इसके बजाय {{code|ArrayList<Object>}} ऑब्जेक्ट का उपयोग करके {{code|Collection<Object>}} का उदाहरण बनाकर इस समस्या को ठीक किया जा सकता है। जावा SE7 या बाद के संस्करणों का उपयोग करने वाले कोड के लिए, {{code|Collection<Object>}} को डायमंड ऑपरेटर का उपयोग करके {{code|ArrayList<>}} ऑब्जेक्ट के साथ त्वरित किया जा सकता है।
यदि डेवलपर {{code|Collection<Object>}} ऑब्जेक्ट घोषित करता है और रिटर्न टाइप {{code|ArrayList<Long>}} के साथ इस ऑब्जेक्ट का नया उदाहरण बनाता है, तो जावा कंपाइलर (सही ढंग से) असंगत टाइपों की उपस्थिति को इंगित करने के लिए संकलन-समय अपवाद फेंक देगा (क्योंकि जेनेरिक हैं)।{{sfn|Bloch|2018|loc=Chapter §5 Item 28: Prefer lists to arrays|pp=126-129}} इसलिए, यह संभावित रन-टाइम अपवादों से बचा जाता है। इसके बजाय {{code|ArrayList<Object>}} ऑब्जेक्ट का उपयोग करके {{code|Collection<Object>}} का उदाहरण बनाकर इस समस्या को ठीक किया जा सकता है। जावा SE7 या बाद के संस्करणों का उपयोग करने वाले कोड के लिए, {{code|Collection<Object>}} को डायमंड ऑपरेटर का उपयोग करके {{code|ArrayList<>}} ऑब्जेक्ट के साथ त्वरित किया जा सकता है।


=== पुनःकरण ===
=== पुनःकरण ===
{{main article|रीफिकेशन (कंप्यूटर विज्ञान)}}
{{main article|रीफिकेशन (कंप्यूटर विज्ञान)}}


ऐरे को पुनरीक्षित किया जाता है, जिसका अर्थ है कि ऐरे ऑब्जेक्ट रन-टाइम पर अपने प्रकार की जानकारी को प्रयुक्त करता है, जबकि '''जावा में जेनेरिक''' को पुन: संशोधित नहीं किया जाता है।{{sfn|Bloch|2018|loc=Chapter §5 Item 28: Prefer lists to arrays|pp=126-129}}
ऐरे को पुनरीक्षित किया जाता है, जिसका अर्थ है कि ऐरे ऑब्जेक्ट रन-टाइम पर अपने टाइप की जानकारी को प्रयुक्त करता है, जबकि '''जावा में जेनेरिक''' को पुन: संशोधित नहीं किया जाता है।{{sfn|Bloch|2018|loc=Chapter §5 Item 28: Prefer lists to arrays|pp=126-129}}


अधिक औपचारिक रूप से कहें तो, जावा में सामान्य प्रकार वाली वस्तुएं गैर-शोधन योग्य प्रकार हैं।{{sfn|Bloch|2018|loc=Chapter §5 Item 28: Prefer lists to arrays|pp=126-129}} गैर-शोधन योग्य प्रकार वह प्रकार है, जिसका रन-टाइम पर प्रतिनिधित्व में संकलन-समय पर इसके प्रतिनिधित्व की तुलना में कम जानकारी होती है।{{sfn|Bloch|2018|loc=Chapter §5 Item 28: Prefer lists to arrays|pp=126-129}}
अधिक औपचारिक रूप से कहें तो, जावा में सामान्य टाइप वाली वस्तुएं गैर-शोधन योग्य टाइप हैं।{{sfn|Bloch|2018|loc=Chapter §5 Item 28: Prefer lists to arrays|pp=126-129}} गैर-शोधन योग्य टाइप वह टाइप है, जिसका रन-टाइम पर प्रतिनिधित्व में संकलन-समय पर इसके प्रतिनिधित्व की तुलना में कम जानकारी होती है।{{sfn|Bloch|2018|loc=Chapter §5 Item 28: Prefer lists to arrays|pp=126-129}}


जावा में सामान्य प्रकार वाली वस्तुएं प्रकार के क्षरण के कारण पुन:शोधन योग्य नहीं होती हैं।{{sfn|Bloch|2018|loc=Chapter §5 Item 28: Prefer lists to arrays|pp=126-129}} जावा केवल संकलन-समय पर प्रकार की जानकारी प्रयुक्त करता है। संकलन-समय पर प्रकार की जानकारी सत्यापित होने के बाद, प्रकार की जानकारी हटा दी जाती है, और रन-टाइम पर, प्रकार की जानकारी उपलब्ध नहीं होगी।{{sfn|Bloch|2018|loc=Chapter §5 Item 28: Prefer lists to arrays|pp=126-129}}
जावा में सामान्य टाइप वाली वस्तुएं टाइप के क्षरण के कारण पुन:शोधन योग्य नहीं होती हैं।{{sfn|Bloch|2018|loc=Chapter §5 Item 28: Prefer lists to arrays|pp=126-129}} जावा केवल संकलन-समय पर टाइप की जानकारी प्रयुक्त करता है। संकलन-समय पर टाइप की जानकारी सत्यापित होने के बाद, टाइप की जानकारी हटा दी जाती है, और रन-टाइम पर, टाइप की जानकारी उपलब्ध नहीं होगी।{{sfn|Bloch|2018|loc=Chapter §5 Item 28: Prefer lists to arrays|pp=126-129}}


गैर-शोधन योग्य प्रकारों के उदाहरणों में {{code|List<T>}} और {{code|List<String>}} सम्मिलित हैं, जहाँ {{code|T}} सामान्य औपचारिक पैरामीटर है। {{sfn|Bloch|2018|loc=Chapter §5 Item 28: Prefer lists to arrays|pp=126-129}}
गैर-शोधन योग्य टाइपों के उदाहरणों में {{code|List<T>}} और {{code|List<String>}} सम्मिलित हैं, जहाँ {{code|T}} सामान्य औपचारिक पैरामीटर है। {{sfn|Bloch|2018|loc=Chapter §5 Item 28: Prefer lists to arrays|pp=126-129}}


==जेनेरिक पर प्रोजेक्ट==
==जेनेरिक पर प्रोजेक्ट==
Line 277: Line 277:
[[प्रोजेक्ट वल्लाह (जावा भाषा)]] जावा 10 से आगे के संभावित संस्करणों के लिए उत्तम जावा जेनेरिक और भाषा सुविधाओं को विकसित करने के लिए प्रायोगिक परियोजना है। संभावित संवर्द्धन में सम्मिलित हैं:<ref>{{cite web|last1=Goetz|first1=Brian|title=वल्लाह में आपका स्वागत है!|url=http://mail.openjdk.java.net/pipermail/valhalla-dev/2014-July/000000.html|website=OpenJDK mail archive|publisher=OpenJDK|access-date=12 August 2014}}</ref>
[[प्रोजेक्ट वल्लाह (जावा भाषा)]] जावा 10 से आगे के संभावित संस्करणों के लिए उत्तम जावा जेनेरिक और भाषा सुविधाओं को विकसित करने के लिए प्रायोगिक परियोजना है। संभावित संवर्द्धन में सम्मिलित हैं:<ref>{{cite web|last1=Goetz|first1=Brian|title=वल्लाह में आपका स्वागत है!|url=http://mail.openjdk.java.net/pipermail/valhalla-dev/2014-July/000000.html|website=OpenJDK mail archive|publisher=OpenJDK|access-date=12 August 2014}}</ref>
* सामान्य विशेषज्ञता, उदाहरण List<int>
* सामान्य विशेषज्ञता, उदाहरण List<int>
* रिफाइड जेनेरिक; रनटाइम पर वास्तविक प्रकार उपलब्ध कराना।
* रिफाइड जेनेरिक; रनटाइम पर वास्तविक टाइप उपलब्ध कराना।


==यह भी देखें==
==यह भी देखें==

Revision as of 09:49, 19 July 2023

जेनरिक सामान्य प्रोग्रामिंग की सुविधा है, जिसे 2004 में जावा प्लेटफ़ॉर्म, मानक संस्करण 5.0 के अन्दर जावा (प्रोग्रामिंग भाषा) में जोड़ा गया था। उन्हें संकलन-समय टाइप की सुरक्षा प्रदान करते हुए विभिन्न टाइप की वस्तुओं पर एक टाइप या विधि को संचालित करने की अनुमति देने के लिए जावा के टाइप प्रणाली का विस्तार करने के लिए डिज़ाइन किया गया था।[1] पहलू संकलन-समय टाइप की सुरक्षा पूरी तरह से प्राप्त नहीं की गई थी, क्योंकि 2016 में यह दिखाया गया था कि सभी स्थितियों में इसकी गारंटी नहीं है।[2][3]

जावा संग्रह ढाँचा संग्रह उदाहरण में संग्रहीत वस्तुओं के टाइप को निर्दिष्ट करने के लिए जेनेरिक का समर्थन करता है।

1998 में, गिलाद ब्राचा, मार्टिन ओडर्सकी , डेविड स्टाउटमायर और फिलिप वाडलर ने जेनेरिक जावा बनाया, जो सामान्य टाइपों का समर्थन करने के लिए जावा भाषा का विस्तार था।[4] जेनेरिक जावा को वाइल्डकार्ड (जावा) के साथ जावा में सम्मिलित किया गया था।

पदानुक्रम और वर्गीकरण

जावा भाषा विशिष्टता के अनुसार:[5]

  • एक टाइप का चर अयोग्य पहचानकर्ता है। टाइप चर को जेनेरिक क्लास डिक्लेरेशन, जेनेरिक इंटरफ़ेस डिक्लेरेशन, जेनेरिक मेथड डिक्लेरेशन और जेनेरिक कंस्ट्रक्टर डिक्लेरेशन द्वारा प्रस्तुत किया जाता है।
  • वर्ग सामान्य है, यदि वह एक या अधिक टाइप के चर घोषित करता है।[6] यह एक या अधिक टाइप के वेरिएबल को परिभाषित करता है, जो पैरामीटर के रूप में कार्य करते हैं।[7] सामान्य वर्ग घोषणा पैरामीटरयुक्त टाइपों के सेट को परिभाषित करती है, जो टाइप पैरामीटर अनुभाग के प्रत्येक संभावित आह्वान के लिए एक है। ये सभी पैरामीटरयुक्त टाइप रनटाइम पर एक ही क्लास साझा करते हैं।
  • इंटरफ़ेस (जावा) सामान्य है यदि यह एक या अधिक टाइप के चर घोषित करता है।[7] यह एक या अधिक टाइप के वेरिएबल को परिभाषित करता है, जो पैरामीटर के रूप में कार्य करते हैं।[7] सामान्य इंटरफ़ेस घोषणा टाइप के सेट को परिभाषित करती है, टाइप पैरामीटर अनुभाग के प्रत्येक संभावित आह्वान के लिए एक। सभी पैरामीटरयुक्त टाइप रनटाइम पर समान इंटरफ़ेस साझा करते हैं।
  • विधि सामान्य है यदि यह एक या अधिक टाइप के चर घोषित करती है।[8] इस टाइप के चर को विधि के औपचारिक टाइप के पैरामीटर के रूप में जाना जाता है। औपचारिक टाइप पैरामीटर सूची का रूप किसी वर्ग या इंटरफ़ेस के टाइप पैरामीटर सूची के समान है।
  • कंस्ट्रक्टर को जेनेरिक घोषित किया जा सकता है, चाहे कंस्ट्रक्टर को जिस वर्ग में घोषित किया गया है वह स्वयं जेनेरिक है या नहीं। कंस्ट्रक्टर सामान्य होता है यदि वह एक या अधिक टाइप के वेरिएबल घोषित करता है। इन टाइप के चर को कंस्ट्रक्टर के औपचारिक टाइप के पैरामीटर के रूप में जाना जाता है। औपचारिक टाइप पैरामीटर सूची का रूप सामान्य वर्ग या इंटरफ़ेस की टाइप पैरामीटर सूची के समान है।

प्रेरणा

जावा कोड का निम्नलिखित ब्लॉक उस समस्या को दर्शाता है, जो जेनेरिक का उपयोग न करने पर उपलब्ध होती है। सबसे पहले, यह Object टाइप की ArrayList घोषित करता है। फिर, यह ArrayList में String जोड़ता है। अंत में, यह जोड़े गए String को पुनः प्राप्त करने का प्रयास करता है और इसे Integer में डालने का प्रयास करता है - लॉजिक में त्रुटि, क्योंकि सामान्यतः पूर्णांक में इच्छानुसार स्ट्रिंग डालना संभव नहीं है।

final List v = new ArrayList();
v.add("test"); // A String that cannot be cast to an Integer
final Integer i = (Integer) v.get(0); // Run time error

चूँकि कोड बिना किसी त्रुटि के संकलित किया गया है, यह कोड की तीसरी लाइन निष्पादित करते समय रनटाइम अपवाद (java.lang.ClassCastException) फेंकता है। जेनरिक का उपयोग करके संकलन समय के समय इस टाइप की लॉजिक त्रुटि का पता लगाया जा सकता है[7] और उनका उपयोग करने के लिए प्राथमिक प्रेरणा है।[6] यह एक या अधिक टाइप के वेरिएबल को परिभाषित करता है, जो पैरामीटर के रूप में कार्य करते हैं।

उपरोक्त कोड खंड को जेनेरिक का उपयोग करके निम्नानुसार फिर से लिखा जा सकता है:

final List<String> v = new ArrayList<String>();
v.add("test");
final Integer i = (Integer) v.get(0); // (type error)  compilation-time error

कोण कोष्ठक के अन्दर टाइप पैरामीटर String ArrayList को String (ArrayList के सामान्य Object घटकों का वंशज) से गठित होने की घोषणा करता है। जेनेरिक के साथ, तीसरी लाइन को किसी विशेष टाइप में डालना अब आवश्यक नहीं है, क्योंकि v.get(0) के परिणाम को कंपाइलर द्वारा उत्पन्न कोड द्वारा String के रूप में परिभाषित किया गया है।

इस खंड की तीसरी लाइन में तार्किक दोष को संकलन-समय त्रुटि (J2SE 5.0 या बाद के संस्करण के साथ) के रूप में पहचाना जाएगा क्योंकि कंपाइलर यह पता लगाएगा कि v.get(0) Integer पूर्णांक के अतिरिक्त String लौटाता है।[7] अधिक विस्तृत उदाहरण के लिए, संदर्भ देखें।[9]

यहां पैकेज java.util में इंटरफेस java.util.List और java.util.Iterator की परिभाषा से छोटा सा अंश दिया गया है:

interface List<E> { 

    void add(E x);
    Iterator<E> iterator();

}

interface Iterator<E> {

    E next();
    boolean hasNext();

}


सामान्य वर्ग परिभाषाएँ

यहां सामान्य जावा क्लास का उदाहरण दिया गया है, जिसका उपयोग मानचित्र (कंप्यूटर विज्ञान) में व्यक्तिगत प्रविष्टियों (वैल्यू मैपिंग की कुंजी) को दर्शाने के लिए किया जा सकता है:

public class Entry<KeyType, ValueType> {
  
    private final KeyType key;
    private final ValueType value;

    public Entry(KeyType key, ValueType value) {  
        this.key = key;
        this.value = value;
    }

    public KeyType getKey() {
        return key;
    }

    public ValueType getValue() {
        return value;
    }

    public String toString() { 
        return "(" + key + ", " + value + ")";  
    }

}

इस सामान्य वर्ग का उपयोग निम्नलिखित विधियों से किया जा सकता है, उदाहरण के लिए:

final Entry<String, String> grade = new Entry<String, String>("Mike", "A");
final Entry<String, Integer> mark = new Entry<String, Integer>("Mike", 100);
System.out.println("grade: " + grade);
System.out.println("mark: " + mark);

final Entry<Integer, Boolean> prime = new Entry<Integer, Boolean>(13, true);
if (prime.getValue()) {
    System.out.println(prime.getKey() + " is prime.");
}
else {
    System.out.println(prime.getKey() + " is not prime.");
}

यह आउटपुट देता है:

grade: (Mike, A)
mark: (Mike, 100)
13 is prime.

सामान्य विधि परिभाषाएँ

उपरोक्त सामान्य वर्ग का उपयोग करते हुए सामान्य विधि का उदाहरण यहां दिया गया है:

public static <Type> Entry<Type, Type> twice(Type value) {
    return new Entry<Type, Type>(value, value);
}

नोट: यदि हम पहले <Type> को हटा दें, उपरोक्त विधि में, हमें संकलन त्रुटि मिलेगी (प्रतीक टाइप नहीं मिल सका), क्योंकि यह प्रतीक की घोषणा का प्रतिनिधित्व करता है।

कई स्थितियों में, विधि के उपयोगकर्ता को टाइप के पैरामीटर को इंगित करने की आवश्यकता नहीं होती है, क्योंकि उनका अनुमान लगाया जा सकता है:

final Entry<String, String> pair = Entry.twice("Hello");

यदि आवश्यक हो तो पैरामीटर स्पष्ट रूप से जोड़े जा सकते हैं:

final Entry<String, String> pair = Entry.<String>twice("Hello");

आदिम टाइप के उपयोग की अनुमति नहीं है, और इसके अतिरिक्त ऑब्जेक्ट टाइप (ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग) बॉक्सिंग संस्करणों का उपयोग किया जाना चाहिए:

final Entry<int, int> pair; // Fails compilation. Use Integer instead.

दिए गए पैरामीटर के आधार पर सामान्य विधि बनाने की भी संभावना है।

public <Type> Type[] toArray(Type... elements) {
    return elements;
}

ऐसी स्थितियों में आप आदिम टाइपों का भी उपयोग नहीं कर सकते, उदाहरण के लिए:

Integer[] array = toArray(1, 2, 3, 4, 5, 6);


डायमंड ऑपरेटर

टाइप के अनुमान के लिए धन्यवाद, जावा एसई 7 और इसके बाद के संस्करण प्रोग्रामर को कोण कोष्ठक की खाली जोड़ी (<>, जिसे डायमंड ऑपरेटर कहा जाता है) को कोण कोष्ठक की जोड़ी के लिए प्रतिस्थापित करने की अनुमति देता है जिसमें एक या अधिक टाइप के पैरामीटर होते हैं जो पर्याप्त रूप से बंद संदर्भ का तात्पर्य है।[10] इस टाइप, Entry का उपयोग करके उपरोक्त कोड उदाहरण को इस टाइप पुनः लिखा जा सकता है:

final Entry<String, String> grade = new Entry<>("Mike", "A");
final Entry<String, Integer> mark = new Entry<>("Mike", 100);
System.out.println("grade: " + grade);
System.out.println("mark: " + mark);

final Entry<Integer, Boolean> prime = new Entry<>(13, true);
if (prime.getValue()) System.out.println(prime.getKey() + " is prime.");
else System.out.println(prime.getKey() + " is not prime.");


वाइल्डकार्ड टाइप करें

पैरामीटरयुक्त टाइप के लिए एक टाइप का लॉजिक किसी ठोस वर्ग या इंटरफ़ेस तक सीमित नहीं है। जावा पैरामीटरयुक्त टाइपों के लिए टाइप के लॉजिक के रूप में "टाइप वाइल्डकार्ड" के उपयोग की अनुमति देता है। वाइल्डकार्ड "<?>" रूप में टाइप के लॉजिक हैं; वैकल्पिक रूप से ऊपरी या निचली सीमा के साथ। यह देखते हुए कि वाइल्डकार्ड द्वारा दर्शाया गया स्पष्ट टाइप अज्ञात है, उन विधियों के टाइप पर प्रतिबंध लगाए जाते हैं जिन्हें किसी ऑब्जेक्ट पर बुलाया जा सकता है जो पैरामीटरयुक्त टाइपों का उपयोग करता है।

यहां उदाहरण दिया गया है, जहां Collection<E> के तत्व टाइप को वाइल्डकार्ड द्वारा पैरामीटराइज़ किया गया है:

final Collection<?> c = new ArrayList<String>();
c.add(new Object()); // compile-time error
c.add(null); // allowed

चूँकि हम नहीं जानते कि तत्व टाइप c का क्या अर्थ है, हम इसमें ऑब्जेक्ट नहीं जोड़ सकते। add() विधि E e> टाइप के लॉजिक लेती है, जो कि Collection<E> जेनेरिक इंटरफ़ेस का तत्व टाइप है। जब वास्तविक टाइप का लॉजिक ? होता है, तो यह किसी अज्ञात टाइप का प्रतिनिधित्व करता है। add() विधि में हम जो भी विधि लॉजिक मान पास करते हैं वह इस अज्ञात टाइप का उपटाइप होना चाहिए। चूँकि हम नहीं जानते कि वह किस टाइप का है, हम कुछ भी पारित नहीं कर सकते हैं। एकमात्र अपवाद शून्य है; जो हर टाइप का सदस्य है।[11]

किसी टाइप के वाइल्डकार्ड की ऊपरी सीमा को निर्दिष्ट करने के लिए, extends कीवर्ड का उपयोग यह इंगित करने के लिए किया जाता है कि टाइप लॉजिक बाउंडिंग क्लास का उपटाइप है।[12] तो List<? extends Number> का अर्थ है कि दी गई सूची में कुछ अज्ञात टाइप की वस्तुएं हैं जो Number वर्ग का विस्तार करती हैं। उदाहरण के लिए, सूची List<Float> या List<Number> हो सकती है। सूची से किसी तत्व को पढ़ने पर Number वापस आ जाएगी। फिर से, अशक्त तत्वों को जोड़ने की भी अनुमति है।[13]

उपरोक्त वाइल्डकार्ड का उपयोग लचीलापन जोड़ता है[12] क्योंकि ठोस टाइप के लॉजिक के साथ किन्हीं दो पैरामीटरयुक्त टाइपों के बीच कोई विरासत संबंध नहीं है। न तो List<Number> और न ही List<Integer> दूसरे का उपटाइप है; तथापि Integer Number का उपटाइप है।[12] इसलिए, कोई भी विधि जो List<Number> को पैरामीटर के रूप में लेती है, List<Integer> के लॉजिक को स्वीकार नहीं करती है। यदि ऐसा होता, तो इसमें ऐसा Number सम्मिलित करना संभव होता जो Integer नहीं है; जो टाइप की सुरक्षा का उल्लंघन करता है। यहां उदाहरण दिया गया है जो दर्शाता है कि यदि List<Integer> List<Number> का उपटाइप होता तो किस टाइप टाइप की सुरक्षा का उल्लंघन किया जाता:

final List<Integer> ints = new ArrayList<>();
ints.add(2);
final List<Number> nums = ints;  // valid if List<Integer> were a subtype of List<Number> according to substitution rule. 
nums.add(3.14);  
final Integer x = ints.get(1); // now 3.14 is assigned to an Integer variable!

वाइल्डकार्ड के साथ समाधान काम करता है क्योंकि यह उन परिचालनों की अनुमति नहीं देता है जो टाइप की सुरक्षा का उल्लंघन करेंगे:

final List<? extends Number> nums = ints;  // OK
nums.add(3.14); // compile-time error
nums.add(null); // allowed

किसी टाइप के वाइल्डकार्ड के निचले बाउंडिंग वर्ग को निर्दिष्ट करने के लिए, super कीवर्ड का प्रयोग किया जाता है। यह कीवर्ड इंगित करता है कि टाइप लॉजिक बाउंडिंग क्लास का सुपरटाइप है। इसलिए, List<Number> या List<Object> List<? super Number> का प्रतिनिधित्व कर सकता है। List<? के रूप में परिभाषित सूची से पढ़ना super Number> Object टाइप के तत्व लौटाता है। ऐसी सूची में जोड़ने के लिए या तो Number टाइप के तत्वों, Number के किसी उपटाइप या शून्य (जो हर टाइप का सदस्य है) की आवश्यकता होती है।

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

थ्रो क्लॉज़ में जेनरिक

चूँकि अपवाद स्वयं सामान्य नहीं हो सकते, सामान्य पैरामीटर थ्रो क्लॉज में दिखाई दे सकते हैं:

public <T extends Throwable> void throwMeConditional(boolean conditional, T exception) throws T {
    if (conditional) {
        throw exception;
    }
}


टाइप मिटाने की समस्या

टाइप-शुद्धता के लिए संकलन-समय पर जेनेरिक की जाँच की जाती है।[7] सामान्य टाइप की जानकारी को टाइप मिटाना नामक प्रक्रिया में हटा दिया जाता है।[6] उदाहरण के लिए, List<Integer> गैर-जेनेरिक Listटाइप में परिवर्तित कर दिया जाएगा, जिसमें सामान्यतः इच्छानुसार वस्तुएं सम्मिलित होती हैं। संकलन-समय जांच यह गारंटी देती है कि परिणामी कोड सही टाइप का उपयोग करता है।[7]

टाइप के क्षरण के कारण, रन-टाइम पर टाइप के पैरामीटर निर्धारित नहीं किए जा सकते।[6] उदाहरण के लिए, जब रनटाइम पर ArrayList की जांच की जाती है, तो यह निर्धारित करने का कोई सामान्य विधि नहीं है कि, टाइप मिटाने से पहले, यह ArrayList<Integer> था या ArrayList<Float> था। कई लोग इस प्रतिबंध से असंतुष्ट हैं।[14] यह आंशिक दृष्टिकोण हैं। उदाहरण के लिए, व्यक्तिगत तत्वों की जांच यह निर्धारित करने के लिए की जा सकती है कि वे किस टाइप के हैं; उदाहरण के लिए, यदि किसी ArrayList में Integer है, तो उस ArrayList को Integer के साथ पैरामीटराइज़ किया गया हो सकता है (चूँकि, इसे Integer के किसी भी पैरेंट, जैसे Number या Object) के साथ पैरामीटराइज़ किया गया हो सकता है।

इस बिंदु को प्रदर्शित करते हुए, निम्नलिखित कोड समान आउटपुट देता है:

final List<Integer> li = new ArrayList<>();
final List<Float> lf = new ArrayList<>();
if (li.getClass() == lf.getClass()) { // evaluates to true
    System.out.println("Equal");
}

टाइप के क्षरण का अन्य प्रभाव यह है कि सामान्य वर्ग किसी भी तरह से, प्रत्यक्ष या अप्रत्यक्ष रूप से, Throwable वर्ग का विस्तार नहीं कर सकता है:[15]

public class GenericException<T> extends Exception

इसके समर्थित न होने का कारण टाइप का क्षरण है:

try {
    throw new GenericException<Integer>();
}
catch (GenericException<Integer> e) {
    System.err.println("Integer");
}
catch (GenericException<String> e) {
    System.err.println("String");
}

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

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

उदाहरण के लिए, निम्नलिखित कोड संकलित नहीं किया जा सकता:

<T> T instantiateElementType(List<T> arg) {
     return new T(); //causes a compile error
}

चूँकि रनटाइम पर प्रति जेनेरिक क्लास की केवल प्रतिलिपि होती है, स्थैतिक चर को क्लास के सभी उदाहरणों के बीच साझा किया जाता है, चाहे उनके टाइप के पैरामीटर कुछ भी हों। परिणामस्वरूप, टाइप पैरामीटर का उपयोग स्थिर चर की घोषणा में या स्थिर विधियों में नहीं किया जा सकता है।

जावा SE5 से पहले लिखे गए प्रोग्रामों के साथ बैकवर्ड संगतता बनाए रखने के लिए जावा में टाइप इरेज़र प्रयुक्त किया गया था।[7]

सरणी से अंतर

जावा में ऐरे (आदिम ऐरे और Object ऐरे दोनों) और जेनेरिक के बीच कई महत्वपूर्ण अंतर हैं। दो प्रमुख अंतर, अर्थात् विचरण और रीफिकेशन के संदर्भ में अंतर।

सहप्रसरण, प्रतिप्रसरण और अपरिवर्तन

जेनेरिक अपरिवर्तनीय हैं, जबकि सरणियाँ सहप्रसरण और प्रतिप्रसरण (कंप्यूटर विज्ञान) हैं।[6] ऐरे जैसी गैर-जेनेरिक वस्तुओं की तुलना में जेनेरिक का उपयोग करने का यह लाभ है।[6] विशेष रूप से, जेनरिक डेवलपर को कोड को ठीक करने के लिए विवश करने के लिए संकलन-समय अपवाद फेंककर रन टाइम अपवादों को रोकने में सहायता कर सकता है।

उदाहरण के लिए, यदि कोई डेवलपर Object[] ऑब्जेक्ट घोषित करता है और ऑब्जेक्ट को नए Long[]] ऑब्जेक्ट के रूप में इंस्टेंट करता है, तो कोई संकलन-समय अपवाद नहीं फेंका जाता है (क्योंकि एरे सहसंयोजक होते हैं)।[6] इससे यह ग़लत धारणा बन सकती है कि कोड सही ढंग से लिखा गया है। चूँकि, यदि डेवलपर इस Long[] ऑब्जेक्ट में String जोड़ने का प्रयास करता है, तो प्रोग्राम ArrayStoreException फेंक देगा।[6] यदि डेवलपर जेनेरिक का उपयोग करता है तो इस रन-टाइम अपवाद से पूरी तरह बचा जा सकता है।

यदि डेवलपर Collection<Object> ऑब्जेक्ट घोषित करता है और रिटर्न टाइप ArrayList<Long> के साथ इस ऑब्जेक्ट का नया उदाहरण बनाता है, तो जावा कंपाइलर (सही ढंग से) असंगत टाइपों की उपस्थिति को इंगित करने के लिए संकलन-समय अपवाद फेंक देगा (क्योंकि जेनेरिक हैं)।[6] इसलिए, यह संभावित रन-टाइम अपवादों से बचा जाता है। इसके बजाय ArrayList<Object> ऑब्जेक्ट का उपयोग करके Collection<Object> का उदाहरण बनाकर इस समस्या को ठीक किया जा सकता है। जावा SE7 या बाद के संस्करणों का उपयोग करने वाले कोड के लिए, Collection<Object> को डायमंड ऑपरेटर का उपयोग करके ArrayList<> ऑब्जेक्ट के साथ त्वरित किया जा सकता है।

पुनःकरण

ऐरे को पुनरीक्षित किया जाता है, जिसका अर्थ है कि ऐरे ऑब्जेक्ट रन-टाइम पर अपने टाइप की जानकारी को प्रयुक्त करता है, जबकि जावा में जेनेरिक को पुन: संशोधित नहीं किया जाता है।[6]

अधिक औपचारिक रूप से कहें तो, जावा में सामान्य टाइप वाली वस्तुएं गैर-शोधन योग्य टाइप हैं।[6] गैर-शोधन योग्य टाइप वह टाइप है, जिसका रन-टाइम पर प्रतिनिधित्व में संकलन-समय पर इसके प्रतिनिधित्व की तुलना में कम जानकारी होती है।[6]

जावा में सामान्य टाइप वाली वस्तुएं टाइप के क्षरण के कारण पुन:शोधन योग्य नहीं होती हैं।[6] जावा केवल संकलन-समय पर टाइप की जानकारी प्रयुक्त करता है। संकलन-समय पर टाइप की जानकारी सत्यापित होने के बाद, टाइप की जानकारी हटा दी जाती है, और रन-टाइम पर, टाइप की जानकारी उपलब्ध नहीं होगी।[6]

गैर-शोधन योग्य टाइपों के उदाहरणों में List<T> और List<String> सम्मिलित हैं, जहाँ T सामान्य औपचारिक पैरामीटर है। [6]

जेनेरिक पर प्रोजेक्ट

प्रोजेक्ट वल्लाह (जावा भाषा) जावा 10 से आगे के संभावित संस्करणों के लिए उत्तम जावा जेनेरिक और भाषा सुविधाओं को विकसित करने के लिए प्रायोगिक परियोजना है। संभावित संवर्द्धन में सम्मिलित हैं:[16]

  • सामान्य विशेषज्ञता, उदाहरण List<int>
  • रिफाइड जेनेरिक; रनटाइम पर वास्तविक टाइप उपलब्ध कराना।

यह भी देखें

उद्धरण

  1. Java Programming Language
  2. A ClassCastException can be thrown even in the absence of casts or nulls."Java and Scala's Type Systems are Unsound" (PDF).
  3. Bloch 2018, pp. 123–125, Chapter §5 Item 27: Eliminate unchecked warnings.
  4. GJ: Generic Java
  5. Java Language Specification, Third Edition by James Gosling, Bill Joy, Guy Steele, Gilad Bracha – Prentice Hall PTR 2005
  6. 6.00 6.01 6.02 6.03 6.04 6.05 6.06 6.07 6.08 6.09 6.10 6.11 6.12 6.13 6.14 Bloch 2018, pp. 126–129, Chapter §5 Item 28: Prefer lists to arrays.
  7. 7.0 7.1 7.2 7.3 7.4 7.5 7.6 7.7 Bloch 2018, pp. 117–122, Chapter §5 Item 26: Don't use raw types.
  8. Bloch 2018, pp. 135–138, Chapter §5 Item 30: Favor generic methods.
  9. Gilad Bracha (July 5, 2004). "जावा प्रोग्रामिंग भाषा में जेनेरिक" (PDF). www.oracle.com.
  10. "Type Inference for Generic Instance Creation".
  11. Gilad Bracha (July 5, 2004). "जावा प्रोग्रामिंग भाषा में जेनेरिक" (PDF). www.oracle.com. p. 5.
  12. 12.0 12.1 12.2 12.3 Bloch 2018, pp. 139–145, Chapter §5 Item 31: Use bounded wildcards to increase API flexibility.
  13. Bracha, Gilad. "Wildcards > Bonus > Generics". The Java™ Tutorials. Oracle. ...The sole exception is null, which is a member of every type...
  14. Gafter, Neal (2006-11-05). "जावा के लिए परिष्कृत जेनेरिक". Retrieved 2010-04-20.
  15. "Java Language Specification, Section 8.1.2". Oracle. Retrieved 24 October 2015.
  16. Goetz, Brian. "वल्लाह में आपका स्वागत है!". OpenJDK mail archive. OpenJDK. Retrieved 12 August 2014.


संदर्भ

  • Bloch, Joshua (2018). "Effective Java: Programming Language Guide" (third ed.). Addison-Wesley. ISBN 978-0134685991.