जावा में जेनेरिक कक्षाओं के साथ क्यों काम करते हैं लेकिन आदिम प्रकारों के साथ नहीं?
उदाहरण के लिए, यह ठीक काम करता है:
List<Integer> foo = new ArrayList<Integer>();
लेकिन इसकी अनुमति नहीं है:
List<int> bar = new ArrayList<int>();
जावा में जेनेरिक कक्षाओं के साथ क्यों काम करते हैं लेकिन आदिम प्रकारों के साथ नहीं?
उदाहरण के लिए, यह ठीक काम करता है:
List<Integer> foo = new ArrayList<Integer>();
लेकिन इसकी अनुमति नहीं है:
List<int> bar = new ArrayList<int>();
जवाबों:
जावा में जेनेरिक एक पूरी तरह से संकलन-समय का निर्माण है - कंपाइलर सभी जेनेरिक उपयोगों को सही प्रकार में शामिल करता है। यह पिछले JVM रनटाइम के साथ बैकवर्ड संगतता बनाए रखने के लिए है।
यह:
List<ClassA> list = new ArrayList<ClassA>();
list.add(new ClassA());
ClassA a = list.get(0);
में बदल जाता है (लगभग):
List list = new ArrayList();
list.add(new ClassA());
ClassA a = (ClassA)list.get(0);
इसलिए, जेनेरिक के रूप में उपयोग की जाने वाली किसी भी वस्तु को ऑब्जेक्ट में कनवर्ट करना पड़ता है (इस उदाहरण में get(0)
रिटर्न ए Object
), और आदिम प्रकार नहीं हैं। इसलिए इनका उपयोग जेनरिक में नहीं किया जा सकता है।
जावा में, जेनेरिक उस तरीके से काम करते हैं जो वे करते हैं ... कम से कम भाग में ... क्योंकि भाषा 1 डिजाइन किए जाने के कई साल बाद उन्हें भाषा में जोड़ा गया था । भाषा डिजाइनरों को जेनेरिक के लिए अपने विकल्पों में विवश किया गया था ताकि एक डिजाइन के साथ आ सके जो मौजूदा भाषा और जावा वर्ग के पुस्तकालय के साथ पीछे की ओर संगत था ।
अन्य प्रोग्रामिंग भाषाएं (जैसे C ++, C #, Ada) आदिम प्रकारों को जेनरिक के लिए पैरामीटर प्रकार के रूप में उपयोग करने की अनुमति देती हैं। लेकिन ऐसा करने का दूसरा पक्ष यह है कि इस तरह की भाषाएं जेनरिक (या टेम्प्लेट प्रकार) के कार्यान्वयन आमतौर पर प्रत्येक प्रकार के मानकीकरण के लिए जेनेरिक प्रकार की एक अलग प्रतिलिपि की पीढ़ी उत्पन्न करती हैं।
1 - जावा 1.0 में जेनेरिक कारणों को शामिल नहीं किया गया था क्योंकि यह समय के दबाव के कारण था। उन्होंने महसूस किया कि उन्हें वेब ब्राउज़र द्वारा प्रस्तुत नए बाजार के अवसर को भरने के लिए जावा भाषा को जल्दी से जारी करना था। जेम्स गोसलिंग ने कहा है कि अगर उनके पास समय होता तो वे जेनेरिक को शामिल करना पसंद करते। जावा भाषा क्या दिखती होगी अगर ऐसा हुआ होता तो किसी का अनुमान नहीं होता।
जावा में पिछड़े अनुकूलता के लिए "टाइप इरेज़र" का उपयोग करके जेनेरिक को लागू किया जाता है। सभी सामान्य प्रकार को रनटाइम पर ऑब्जेक्ट में बदल दिया जाता है। उदाहरण के लिए,
public class Container<T> {
private T data;
public T getData() {
return data;
}
}
रनटाइम पर देखा जाएगा,
public class Container {
private Object data;
public Object getData() {
return data;
}
}
कंपाइलर जिम्मेदार है कि टाइप सेफ्टी सुनिश्चित करने के लिए उचित कास्ट उपलब्ध कराए।
Container<Integer> val = new Container<Integer>();
Integer data = val.getData()
हो जाएगा
Container val = new Container();
Integer data = (Integer) val.getData()
अब सवाल यह है कि "ऑब्जेक्ट" को रनटाइम के प्रकार के रूप में क्यों चुना गया है?
उत्तर ऑब्जेक्ट सभी वस्तुओं का सुपरक्लास है और किसी भी उपयोगकर्ता परिभाषित वस्तु का प्रतिनिधित्व कर सकता है।
चूंकि सभी प्राइमेटिव्स को " ऑब्जेक्ट " से विरासत में नहीं मिला है, इसलिए हम इसे सामान्य प्रकार के रूप में उपयोग नहीं कर सकते हैं।
FYI करें: प्रोजेक्ट वल्लाह इस मुद्दे से ऊपर उठने की कोशिश कर रहा है।
संग्रह को एक प्रकार की आवश्यकता के लिए परिभाषित किया गया है जो इससे प्राप्त होता है java.lang.Object
। बसपा के लोग ऐसा नहीं करते हैं।
जावा दस्तावेज़ीकरण के अनुसार , सामान्य प्रकार के चर केवल संदर्भ प्रकारों के साथ तात्कालिक हो सकते हैं, न कि आदिम प्रकार के।
यह प्रोजेक्ट वल्लाह के तहत जावा 10 में आने वाला है ।
में ब्रायन गोएज़ पर कागज विशेषज्ञता के राज्य
उस कारण के बारे में एक उत्कृष्ट व्याख्या है जिसके लिए आदिम के लिए सामान्य समर्थन नहीं किया गया था। और, जावा के भविष्य के रिलीज में इसे कैसे लागू किया जाएगा।
जावा का वर्तमान मिटाया गया कार्यान्वयन जो सभी संदर्भ तात्कालिकता के लिए एक वर्ग का उत्पादन करता है और आदिम तात्कालिकता के लिए कोई समर्थन नहीं करता है। (यह एक सजातीय अनुवाद है, और जावा के जेनरिक केवल संदर्भ प्रकारों की सीमा तक हो सकते हैं, सजातीय अनुवाद की सीमाओं से आता है जो जेवीएम के बाईटकोड सेट के संबंध में है, जो संदर्भ प्रकारों बनाम आदिम प्रकारों के संचालन के लिए अलग-अलग बाईटकोड का उपयोग करता है।) हालांकि, जावा में मिटाए गए जेनेरिक व्यवहार व्यवहार संबंधीता (जेनेरिक तरीके) और डेटा पैरामीट्रिकिटी (जेनेरिक प्रकार के कच्चे और वाइल्डकार्ड इंस्टेंटिएशन) प्रदान करते हैं।
...
एक सजातीय अनुवाद रणनीति को चुना गया, जहां जेनेरिक प्रकार के चर को उनकी सीमा में मिटा दिया जाता है क्योंकि वे बायटेकोड में शामिल हो जाते हैं। इसका मतलब यह है कि एक वर्ग सामान्य है या नहीं, यह अभी भी एक ही वर्ग के लिए संकलित है, एक ही नाम के साथ, और जिनके सदस्य हस्ताक्षर समान हैं। टाइप सुरक्षा को संकलित समय पर सत्यापित किया जाता है, और रनटाइम जेनेरिक प्रकार प्रणाली द्वारा अनफ़िट किया जाता है। बदले में, यह प्रतिबंध लगाया गया था कि जेनरिक केवल संदर्भ प्रकारों पर काम कर सकता है, क्योंकि ऑब्जेक्ट सबसे सामान्य प्रकार उपलब्ध है, और यह आदिम प्रकारों तक विस्तारित नहीं होता है।
ऑब्जेक्ट बनाते समय, आप टाइप पैरामीटर के लिए एक आदिम प्रकार को प्रतिस्थापित नहीं कर सकते हैं। इस प्रतिबंध के कारण, यह एक कंपाइलर कार्यान्वयन मुद्दा है। वर्चुअल मशीन स्टैक पर लोड करने और भंडारण के लिए आदिम प्रकार के अपने बायोटेक निर्देश हैं। इसलिए इन अलग-अलग बायोटेक रास्तों में आदिम जेनेरिकों को संकलित करना असंभव नहीं है, लेकिन यह कंपाइलर को जटिल बना देगा।