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

From Vigyanwiki
No edit summary
Line 12: Line 12:
*वर्ग सामान्य है, यदि वह एक या अधिक प्रकार के चर घोषित करता है।{{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>


यहां पैकेज {{Javadoc:SE|package=java.util|java/util}} में इंटरफेस {{Javadoc:SE|package=java.util|java/util|List}} और {{Javadoc:SE|package=java.util|java/util|Iterator}} की परिभाषा से छोटा सा अंश दिया गया है:
यहां पैकेज {{Javadoc:SE|package=java.util|java/util}} में इंटरफेस {{Javadoc:SE|package=java.util|java/util|List}} और {{Javadoc:SE|package=java.util|java/util|Iterator}} की परिभाषा से छोटा सा अंश दिया गया है:
Line 114: Line 114:
नोट: यदि हम पहले <code><Type></code> को हटा दें, उपरोक्त विधि में, हमें संकलन त्रुटि मिलेगी (प्रतीक प्रकार नहीं मिल सका), क्योंकि यह प्रतीक की घोषणा का प्रतिनिधित्व करता है।
नोट: यदि हम पहले <code><Type></code> को हटा दें, उपरोक्त विधि में, हमें संकलन त्रुटि मिलेगी (प्रतीक प्रकार नहीं मिल सका), क्योंकि यह प्रतीक की घोषणा का प्रतिनिधित्व करता है।


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


<syntaxhighlight lang="Java">
<syntaxhighlight lang="Java">
Line 129: Line 129:
final Entry<int, int> pair; // Fails compilation. Use Integer instead.
final Entry<int, int> pair; // Fails compilation. Use Integer instead.
</syntaxhighlight>
</syntaxhighlight>
दिए गए मापदंडों के आधार पर सामान्य विधि बनाने की भी संभावना है।
दिए गए पैरामीटर के आधार पर सामान्य विधि बनाने की भी संभावना है।


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


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


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

Revision as of 23:24, 18 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.