एरेव्स कोविरेंट हैं
Arrays को सहसंयोजक कहा जाता है जिसका मूल रूप से मतलब है कि, जावा के उप- नियमों को देखते हुए, एक प्रकार के सरणी T[]
में प्रकार T
या किसी भी उप- प्रकार के तत्व शामिल हो सकते हैं T
। उदाहरण के लिए
Number[] numbers = new Number[3];
numbers[0] = newInteger(10);
numbers[1] = newDouble(3.14);
numbers[2] = newByte(0);
लेकिन इतना ही नहीं, जावा के S[]
उप- नियम भी यह कहते हैं कि एक सरणी का एक उपप्रकार है T[]
यदि S
इसका उप-प्रकार है T
, इसलिए, ऐसा कुछ भी मान्य है:
Integer[] myInts = {1,2,3,4};
Number[] myNumber = myInts;
क्योंकि जावा में Integer[]
उप- नियम के अनुसार, एक सरणी एक सरणी का उप-प्रकार हैNumber[]
क्योंकि पूर्णांक संख्या का एक उपप्रकार है।
लेकिन यह उप-नियम नियम एक दिलचस्प सवाल पैदा कर सकता है: अगर हम ऐसा करने की कोशिश करते हैं तो क्या होगा?
myNumber[0] = 3.14; //attempt of heap pollution
यह अंतिम पंक्ति बस ठीक संकलित करेगी, लेकिन यदि हम इस कोड को चलाते हैं, तो हमें ए ArrayStoreException
क्योंकि हम एक पूर्णांक सरणी में एक डबल डालने की कोशिश कर रहे हैं। तथ्य यह है कि हम एक संख्या संदर्भ के माध्यम से सरणी तक पहुंच रहे हैं यहां अप्रासंगिक है, क्या मायने रखता है कि सरणी पूर्णांक का एक सरणी है।
इसका मतलब है कि हम संकलक को मूर्ख बना सकते हैं, लेकिन हम रन-टाइम प्रकार प्रणाली को मूर्ख नहीं बना सकते। और ऐसा इसलिए है क्योंकि सरणियाँ वे हैं जिन्हें हम एक रिफ़ेक्टिव प्रकार कहते हैं। इसका मतलब यह है कि रन-टाइम पर जावा को पता है कि यह सरणी वास्तव में पूर्णांक के एक सरणी के रूप में तात्कालिक थी, जो केवल प्रकार के संदर्भ के माध्यम से एक्सेस करने के लिए होती है।Number[]
।
इसलिए, जैसा कि हम देख सकते हैं, एक चीज वस्तु का वास्तविक प्रकार है, एक अन्य चीज उस संदर्भ का प्रकार है जिसे हम इसे एक्सेस करने के लिए उपयोग करते हैं, है ना?
जावा पीढ़ी के साथ समस्या
अब, जावा में जेनेरिक प्रकारों के साथ समस्या यह है कि कोड के संकलन के बाद कंपाइलर द्वारा टाइप मापदंडों के लिए टाइप की गई जानकारी को छोड़ दिया जाता है; इसलिए इस प्रकार की जानकारी रन टाइम पर उपलब्ध नहीं है। इस प्रक्रिया को टाइप इरेज़र कहा जाता है । जावा में इस तरह की जेनरिक को लागू करने के अच्छे कारण हैं, लेकिन यह एक लंबी कहानी है, और इसे पहले से मौजूद कोड के साथ द्विआधारी संगतता के साथ करना है।
यहां महत्वपूर्ण बिंदु यह है कि चूंकि रन-टाइम पर कोई प्रकार की जानकारी नहीं है, इसलिए यह सुनिश्चित करने का कोई तरीका नहीं है कि हम ढेर प्रदूषण नहीं कर रहे हैं।
आइए अब निम्नलिखित असुरक्षित कोड पर विचार करें:
List<Integer> myInts = newArrayList<Integer>();
myInts.add(1);
myInts.add(2);
List<Number> myNums = myInts; //compiler error
myNums.add(3.14); //heap polution
यदि जावा कंपाइलर हमें ऐसा करने से नहीं रोकता है, तो रन-टाइम टाइप सिस्टम हमें रोक भी नहीं सकता है, क्योंकि रन टाइम में कोई रास्ता नहीं है, यह निर्धारित करने के लिए कि यह सूची केवल पूर्णांकों की सूची होनी चाहिए थी। जावा रन-टाइम हमें इस सूची में जो कुछ भी चाहिए, वह तब डाल देगा, जब इसमें केवल पूर्णांक होना चाहिए, क्योंकि जब इसे बनाया गया था, तो इसे पूर्णांक की सूची के रूप में घोषित किया गया था। यही कारण है कि संकलक लाइन नंबर 4 को अस्वीकार कर देता है क्योंकि यह असुरक्षित है और यदि अनुमति दी गई है तो यह टाइप सिस्टम की मान्यताओं को तोड़ सकता है।
जैसे, जावा के डिजाइनरों ने सुनिश्चित किया कि हम कंपाइलर को बेवकूफ नहीं बना सकते। यदि हम संकलक को बेवकूफ नहीं बना सकते हैं (जैसा कि हम सरणियों के साथ कर सकते हैं) तो हम रन-टाइम प्रकार प्रणाली को भी नहीं बेवकूफ बना सकते हैं।
जैसे, हम कहते हैं कि जेनेरिक प्रकार गैर-पुन: प्रयोज्य हैं, क्योंकि रन टाइम पर हम जेनेरिक प्रकार की सही प्रकृति का निर्धारण नहीं कर सकते हैं।
मैंने इस उत्तर के कुछ हिस्सों को छोड़ दिया है जिसे आप यहाँ पूरा लेख पढ़ सकते हैं:
https://dzone.com/articles/covariance-and-wravravce