जावा जेनरिक आदिम प्रकारों का समर्थन क्यों नहीं करते?


236

जावा में जेनेरिक कक्षाओं के साथ क्यों काम करते हैं लेकिन आदिम प्रकारों के साथ नहीं?

उदाहरण के लिए, यह ठीक काम करता है:

List<Integer> foo = new ArrayList<Integer>();

लेकिन इसकी अनुमति नहीं है:

List<int> bar = new ArrayList<int>();

1
int i = (int) नई वस्तु (); हालांकि ठीक संकलन।
सचिन वर्मा

जवाबों:


243

जावा में जेनेरिक एक पूरी तरह से संकलन-समय का निर्माण है - कंपाइलर सभी जेनेरिक उपयोगों को सही प्रकार में शामिल करता है। यह पिछले 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), और आदिम प्रकार नहीं हैं। इसलिए इनका उपयोग जेनरिक में नहीं किया जा सकता है।


8
@ डैनियल एटेकिन - वास्तव में, जावा जेनरिक को C ++ टेम्प्लेट की तरह बिल्कुल भी नहीं संभाला जाता है ...
स्टीफन C

20
जावा कंपाइलर आदिम प्रकार के बॉक्स को उपयोग में लाने से पहले क्यों नहीं कर सकता है? यह सही होना चाहिए?
vrwim

13
@vrwim - यह संभव हो सकता है। लेकिन यह सिंटैक्टिक शुगर होगा। वास्तविक समस्या यह है कि बॉक्सिंग प्राइमेटिक्स के साथ जावा जेनरिक C ++ / C # मॉडल की तुलना में समय और स्थान दोनों में अपेक्षाकृत महंगा है ... जहां वास्तविक आदिम प्रकार का उपयोग किया जाता है।
स्टीफन सी

6
@MauganRa हाँ मुझे पता है कि मैं कर सकता हूँ :) मैं अपनी जमीन से खड़ा हूँ कि यह भयानक डिजाइन है। उम्मीद है कि यह जावा 10 (या तो मैंने सुना) और उच्च आदेश कार्यों में तय हो जाएगा। मुझे उस पर बोली मत करो।
Ced

4
@Ced इस पर पूरी तरह सहमत है कि यह खराब डिज़ाइन है जो शुरुआती पेशेवरों को समान रूप से चोट पहुँचाता है
MauganRa

37

जावा में, जेनेरिक उस तरीके से काम करते हैं जो वे करते हैं ... कम से कम भाग में ... क्योंकि भाषा 1 डिजाइन किए जाने के कई साल बाद उन्हें भाषा में जोड़ा गया था । भाषा डिजाइनरों को जेनेरिक के लिए अपने विकल्पों में विवश किया गया था ताकि एक डिजाइन के साथ आ सके जो मौजूदा भाषा और जावा वर्ग के पुस्तकालय के साथ पीछे की ओर संगत था ।

अन्य प्रोग्रामिंग भाषाएं (जैसे C ++, C #, Ada) आदिम प्रकारों को जेनरिक के लिए पैरामीटर प्रकार के रूप में उपयोग करने की अनुमति देती हैं। लेकिन ऐसा करने का दूसरा पक्ष यह है कि इस तरह की भाषाएं जेनरिक (या टेम्प्लेट प्रकार) के कार्यान्वयन आमतौर पर प्रत्येक प्रकार के मानकीकरण के लिए जेनेरिक प्रकार की एक अलग प्रतिलिपि की पीढ़ी उत्पन्न करती हैं।


1 - जावा 1.0 में जेनेरिक कारणों को शामिल नहीं किया गया था क्योंकि यह समय के दबाव के कारण था। उन्होंने महसूस किया कि उन्हें वेब ब्राउज़र द्वारा प्रस्तुत नए बाजार के अवसर को भरने के लिए जावा भाषा को जल्दी से जारी करना था। जेम्स गोसलिंग ने कहा है कि अगर उनके पास समय होता तो वे जेनेरिक को शामिल करना पसंद करते। जावा भाषा क्या दिखती होगी अगर ऐसा हुआ होता तो किसी का अनुमान नहीं होता।


11

जावा में पिछड़े अनुकूलता के लिए "टाइप इरेज़र" का उपयोग करके जेनेरिक को लागू किया जाता है। सभी सामान्य प्रकार को रनटाइम पर ऑब्जेक्ट में बदल दिया जाता है। उदाहरण के लिए,

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 करें: प्रोजेक्ट वल्लाह इस मुद्दे से ऊपर उठने की कोशिश कर रहा है।


प्लस 1 उचित नामकरण के लिए।
द्राज़न बेज़ेलोवुक

7

संग्रह को एक प्रकार की आवश्यकता के लिए परिभाषित किया गया है जो इससे प्राप्त होता है java.lang.Object। बसपा के लोग ऐसा नहीं करते हैं।


26
मुझे लगता है कि यहाँ सवाल "क्यों" है। जेनरिक को वस्तुओं की आवश्यकता क्यों होती है? सर्वसम्मति से प्रतीत होता है कि यह डिज़ाइन की पसंद से कम है और पिछड़े संगतता के लिए अधिक कैविंग है। मेरी नजर में, अगर जेनेरिक आदिम को संभाल नहीं सकता है, तो यह एक कार्यक्षमता की कमी है। जैसा कि यह खड़ा है, आदिम से जुड़ी हर चीज को प्रत्येक आदिम के लिए लिखा जाना चाहिए: तुलनित्र <t, t> के बजाय, हमारे पास Integer.compare (int a, int b), Byte.compare (बाइट ए, बाइट बी), आदि हैं। यह एक समाधान नहीं है!
जॉन पी

1
आदिम प्रकारों पर हाँ जेनरिक एक विशेषता होनी चाहिए। यहाँ इसके लिए एक प्रस्ताव का लिंक है openjdk.java.net/jeps/218
कौवा

5

जावा दस्तावेज़ीकरण के अनुसार , सामान्य प्रकार के चर केवल संदर्भ प्रकारों के साथ तात्कालिक हो सकते हैं, न कि आदिम प्रकार के।

यह प्रोजेक्ट वल्लाह के तहत जावा 10 में आने वाला है ।

में ब्रायन गोएज़ पर कागज विशेषज्ञता के राज्य

उस कारण के बारे में एक उत्कृष्ट व्याख्या है जिसके लिए आदिम के लिए सामान्य समर्थन नहीं किया गया था। और, जावा के भविष्य के रिलीज में इसे कैसे लागू किया जाएगा।

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

...

एक सजातीय अनुवाद रणनीति को चुना गया, जहां जेनेरिक प्रकार के चर को उनकी सीमा में मिटा दिया जाता है क्योंकि वे बायटेकोड में शामिल हो जाते हैं। इसका मतलब यह है कि एक वर्ग सामान्य है या नहीं, यह अभी भी एक ही वर्ग के लिए संकलित है, एक ही नाम के साथ, और जिनके सदस्य हस्ताक्षर समान हैं। टाइप सुरक्षा को संकलित समय पर सत्यापित किया जाता है, और रनटाइम जेनेरिक प्रकार प्रणाली द्वारा अनफ़िट किया जाता है। बदले में, यह प्रतिबंध लगाया गया था कि जेनरिक केवल संदर्भ प्रकारों पर काम कर सकता है, क्योंकि ऑब्जेक्ट सबसे सामान्य प्रकार उपलब्ध है, और यह आदिम प्रकारों तक विस्तारित नहीं होता है।


0

ऑब्जेक्ट बनाते समय, आप टाइप पैरामीटर के लिए एक आदिम प्रकार को प्रतिस्थापित नहीं कर सकते हैं। इस प्रतिबंध के कारण, यह एक कंपाइलर कार्यान्वयन मुद्दा है। वर्चुअल मशीन स्टैक पर लोड करने और भंडारण के लिए आदिम प्रकार के अपने बायोटेक निर्देश हैं। इसलिए इन अलग-अलग बायोटेक रास्तों में आदिम जेनेरिकों को संकलित करना असंभव नहीं है, लेकिन यह कंपाइलर को जटिल बना देगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.