सवाल सी ++ और जावा में "जेनेरिक" प्रकारों के बीच अंतर क्या हैं?


जावा में जेनेरिक और सी ++ एक बहुत मजबूत प्रोग्रामिंग मॉडल प्रदान करता है templateरों। तो फिर, सी ++ और जावा जेनरिक के बीच क्या अंतर है?


134
2017-08-30 21:14


मूल


stackoverflow.com/questions/31693 - n611x007


जवाब:


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

template <typename T> T sum(T a, T b) { return a + b; }

उपर्युक्त विधि एक ही प्रकार की दो वस्तुओं को जोड़ती है, और किसी भी प्रकार के टी के लिए इसका उपयोग किया जा सकता है जिसमें "+" ऑपरेटर उपलब्ध है।

जावा में आपको एक प्रकार निर्दिष्ट करना होगा यदि आप पारित वस्तुओं पर विधियों को कॉल करना चाहते हैं, जैसे कुछ:

<T extends Something> T sum(T a, T b) { return a.add ( b ); }

सी ++ जेनेरिक फ़ंक्शंस / कक्षाओं में केवल हेडर में परिभाषित किया जा सकता है, क्योंकि संकलक विभिन्न प्रकारों के लिए अलग-अलग फ़ंक्शन उत्पन्न करता है (जिसे इसके साथ बुलाया जाता है)। तो संकलन धीमा है। जावा में संकलन में कोई बड़ा जुर्माना नहीं होता है, लेकिन जावा "एरर" नामक तकनीक का उपयोग करता है जहां सामान्य प्रकार रनटाइम पर मिटा दिया जाता है, इसलिए रनटाइम जावा वास्तव में कॉल कर रहा है ...

Something sum(Something a, Something b) { return a.add ( b ); }

तो जावा में जेनेरिक प्रोग्रामिंग वास्तव में उपयोगी नहीं है, यह नए फोरैच निर्माण में मदद करने के लिए केवल एक छोटी सी वाक्य रचनात्मक चीनी है।

संपादित करें: उपयोगीता पर उपरोक्त राय एक छोटे से स्वयं द्वारा लिखी गई थी। जावा की जेनेरिक कोर्स की सुरक्षा के साथ मदद करते हैं।


113
2017-08-30 21:34



हाँ, उस अंतिम वाक्य तक बहुत अच्छा जवाब। - Laurence Gonsalves
वह पूरी तरह से सही है कि यह सिर्फ एक विस्तृत वाक्य रचनात्मक चीनी है। - alphazero
यह पूरी तरह से वाक्य रचनात्मक चीनी नहीं है। कंपाइलर जांच प्रकार के लिए इस जानकारी का उपयोग करता है। भले ही जानकारी रनटाइम पर उपलब्ध न हो, मैं संकलित उपयोगों को बस "सिंटेक्टिक चीनी" कहूंगा। यदि आप इसे कॉल करेंगे, तो सी सी असेंबली के लिए सिंटैक्टिक चीनी है, और यह मशीन कोड के लिए सिंटैक्टिक चीनी है :) - dtech
मुझे लगता है सिंटेक्टिक चीनी उपयोगी है। - poitroae
आप एक सामान्य बिंदु को याद करते हैं, जिसे आप जेनेरिक को तुरंत चालू करने के लिए उपयोग कर सकते हैं। सी ++ में टेम्पलेट <int N> का उपयोग करना संभव है और इसे तुरंत चालू करने के लिए उपयोग किए जाने वाले किसी भी नंबर के लिए एक अलग परिणाम प्राप्त करें। इसका उपयोग संकलन समय मेटा प्रोगोगिंग के लिए किया जाता है। उत्तर में पसंद है: stackoverflow.com/questions/189172/c-templates-turing-complete - stonemetal


जावा जेनरिक हैं बड़े पैमाने पर सी ++ टेम्पलेट्स के लिए अलग।

मूल रूप से सी ++ टेम्पलेट्स में मूल रूप से एक गौरवशाली प्रीप्रोसेसर / मैक्रो सेट होता है (ध्यान दें: चूंकि कुछ लोग एक समानता को समझने में असमर्थ लगते हैं, इसलिए मैं नहीं कह रहा हूं कि टेम्पलेट प्रसंस्करण एक मैक्रो है)। जावा में वे मूल रूप से ऑब्जेक्ट्स के बॉयलरप्लेट कास्टिंग को कम करने के लिए सिंटैक्टिक चीनी हैं। यहाँ एक सुंदर सभ्य है जावा जेनरिक बनाम सी ++ टेम्पलेट्स के लिए परिचय

इस बिंदु पर विस्तृत करने के लिए: जब आप एक C ++ टेम्पलेट का उपयोग करते हैं, तो आप मूल रूप से कोड की एक और प्रति बनाते हैं, जैसे कि आपने #define मैक्रो। यह आपको ऐसी चीजों को करने की अनुमति देता है int टेम्पलेट परिभाषाओं में पैरामीटर जो सरणी के आकार निर्धारित करते हैं।

जावा इस तरह काम नहीं करता है। जावा में सभी वस्तुओं की सीमा से java.lang.Object तो, प्री-जेनरिक, आप इस तरह कोड लिखेंगे:

public class PhoneNumbers {
  private Map phoneNumbers = new HashMap();

  public String getPhoneNumber(String name) {
    return (String)phoneNumbers.get(name);
  }

  ...
}

क्योंकि सभी जावा संग्रह प्रकारों ने वस्तु को उनके मूल प्रकार के रूप में उपयोग किया ताकि आप उनमें कुछ भी डाल सकें। जावा 5 चारों ओर रोल करता है और जेनेरिक जोड़ता है ताकि आप चीजें कर सकें:

public class PhoneNumbers {
  private Map<String, String> phoneNumbers = new HashMap<String, String>();

  public String getPhoneNumber(String name) {
    return phoneNumbers.get(name);
  }

  ...
}

और यह सभी जावा जेनरिक हैं: ऑब्जेक्ट कास्टिंग के लिए रैपर। ऐसा इसलिए है क्योंकि जावा जेनरिक परिष्कृत नहीं हैं। वे टाइप एरर का उपयोग करते हैं। यह निर्णय इसलिए बनाया गया था क्योंकि जावा जेनरिक इस टुकड़े में इतने देर से आए थे कि वे पिछड़े संगतता को तोड़ना नहीं चाहते थे (ए Map<String, String> जब भी कोई उपयोग योग्य है Map के लिए बुलाया जाता है)। इसकी तुलना .Net / C # से करें जहां टाइप एरर का उपयोग नहीं किया जाता है, जिससे सभी प्रकार के मतभेद होते हैं (उदाहरण के लिए आप आदिम प्रकारों का उपयोग कर सकते हैं और IEnumerable तथा IEnumerable<T> एक दूसरे से कोई संबंध नहीं है)।

और जावा 5+ कंपाइलर के साथ संकलित जेनिक्स का उपयोग करने वाला एक वर्ग जेडीके 1.4 पर प्रयोग योग्य है (मान लीजिए कि यह जावा 5+ की आवश्यकता वाले किसी अन्य फीचर या क्लासेस का उपयोग नहीं करता है)।

यही कारण है कि जावा जेनरिक कहा जाता है सिंटेक्टिक चीनी

लेकिन जेनेरिकों को कैसे करें इस निर्णय पर गहरा असर पड़ता है ताकि (शानदार) जावा जेनरिक एफएक्यू जावा जेनरिक के बारे में लोगों के कई प्रश्नों के उत्तर देने के लिए उभरा है।

सी ++ टेम्पलेट्स में कई विशेषताएं हैं जो जावा जेनरिक नहीं करते हैं:

  • आदिम प्रकार के तर्कों का उपयोग करें।

    उदाहरण के लिए:

    template<class T, int i>
    class Matrix {
      int T[i][i];
      ...
    }
    

    जावा जेनेरिक में आदिम प्रकार के तर्कों के उपयोग की अनुमति नहीं देता है।

  • का उपयोग डिफ़ॉल्ट प्रकार तर्क, जो एक विशेषता है जिसे मैं जावा में याद करता हूं लेकिन इसके लिए पीछे की संगतता कारण हैं;

  • जावा तर्कों की सीमा को अनुमति देता है।

उदाहरण के लिए:

public class ObservableList<T extends List> {
  ...
}

यह वास्तव में जोर दिया जाना चाहिए कि विभिन्न तर्कों के साथ टेम्पलेट आमंत्रण वास्तव में विभिन्न प्रकार हैं। वे स्थिर सदस्यों को भी साझा नहीं करते हैं। जावा में यह मामला नहीं है।

जेनेरिक के साथ मतभेदों के अलावा, पूर्णता के लिए, यहां एक है सी ++ और जावा की मूल तुलना (तथा और एक)।

और मैं भी सुझाव दे सकता हूं जावा में सोच रहा है। एक सी ++ प्रोग्रामर के रूप में ऑब्जेक्ट्स जैसी कई अवधारणाएं पहले से ही दूसरी प्रकृति होगी लेकिन सूक्ष्म अंतर हैं इसलिए यदि आप भागों को स्किम करते हैं तो भी एक प्रारंभिक पाठ होना उपयोगी हो सकता है।

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


115
2018-01-31 05:22



वे अवधारणा के बराबर नहीं हैं। उत्सुकता से आवर्ती टेम्पलेट पैटर्न होने का सबसे अच्छा उदाहरण है। दूसरी सबसे अच्छी नीति-उन्मुख डिजाइन। तीसरा सबसे अच्छा तथ्य यह है कि सी ++ कोण ब्रैकेट्स (myArray <5>) में अभिन्न संख्याओं को पारित करने की अनुमति देता है। - Max Lybbert
नहीं, वे अवधारणा के बराबर नहीं हैं। अवधारणा में कुछ ओवरलैप है, लेकिन ज्यादा नहीं। दोनों आपको सूची <टी> बनाने की अनुमति देते हैं, लेकिन यह लगभग जहां तक ​​जाता है। सी ++ टेम्पलेट्स बहुत आगे जाते हैं। - jalf
यह ध्यान रखना महत्वपूर्ण है कि प्रकार मिटाए जाने का मुद्दा केवल पीछे की संगतता से अधिक है Map map = new HashMap<String, String>। इसका मतलब है कि आप पुराने कोड को नए कोड पर तैनात कर सकते हैं और यह बाइटकोड में समानताओं के कारण चलाएगा। - Yuval Adam
आप ध्यान देंगे कि मैंने कहा "मूल रूप से एक गौरवशाली प्रीप्रोसेसर / मैक्रो"। यह एक समानता थी क्योंकि प्रत्येक टेम्पलेट घोषणा से अधिक कोड (जावा / सी # के विपरीत) बनाया जाएगा। - cletus
टेम्पलेट कोड है बहुत कॉपी-एंड-पेस्ट से अलग। यदि आप मैक्रो विस्तार के संदर्भ में सोचते हैं, तो जल्दी या बाद में आप इस तरह की सूक्ष्म बगों से प्रभावित होंगे: womble.decadentplace.org.uk/c++/... - Nemanja Trifunovic


सी ++ टेम्पलेट्स है। जावा में जेनेरिक हैं, जो सी ++ टेम्पलेट्स जैसे थोड़े प्रकार की तरह दिखते हैं, लेकिन वे बहुत अलग हैं।

टेम्पलेट्स काम करते हैं, जैसा कि नाम का तात्पर्य है, संकलक को इसके साथ प्रतीक्षा करें (इसके लिए प्रतीक्षा करें ...) टेम्पलेट जिसे टेम्पलेट पैरामीटर भरकर टाइप-सेफ कोड उत्पन्न करने के लिए उपयोग किया जा सकता है।

जेनेरिक, जैसा कि मैं उन्हें समझता हूं, दूसरी तरफ काम करता हूं: टाइप पैरामीटर का उपयोग संकलक द्वारा किया जाता है ताकि यह सत्यापित किया जा सके कि उनका उपयोग करने वाला कोड टाइप-सुरक्षित है, लेकिन परिणामी कोड बिना किसी प्रकार के उत्पन्न होता है।

एक के रूप में सी ++ टेम्पलेट्स के बारे में सोचो वास्तव में अच्छा मैक्रो सिस्टम, और जावा जेनेरिक स्वचालित रूप से टाइपकास्ट उत्पन्न करने के लिए एक उपकरण के रूप में।


73
2017-08-30 21:30



यह एक बहुत अच्छा, संक्षिप्त स्पष्टीकरण है। एक चिमटा मैं यह करने के लिए लुभाना चाहता हूं कि जावा जेनरिक स्वचालित रूप से टाइपकास्ट उत्पन्न करने के लिए एक उपकरण है जो सुरक्षित होने की गारंटी है (कुछ स्थितियों के साथ)। कुछ तरीकों से वे सी ++ से संबंधित हैं const। सी ++ में एक ऑब्जेक्ट को संशोधित नहीं किया जाएगा const पॉइंटर जब तक const-यता दूर जाली है। इसी तरह, जावा में जेनेरिक प्रकारों द्वारा बनाए गए निहित कास्ट को "सुरक्षित" होने की गारंटी दी जाती है जब तक कि प्रकार पैरामीटर मैन्युअल रूप से कोड में कहीं भी नहीं डाले जाते। - Laurence Gonsalves


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


15
2018-01-31 18:23



+1 टेम्पलेट विशेषज्ञता संकलन-समय मेटाप्रोग्रामिंग के लिए अविश्वसनीय रूप से महत्वपूर्ण है - यह अंतर स्वयं जावा जेनिक्स बनाता है जो बहुत कम शक्तिशाली है - Faisal Vali


इस विषय में एक महान स्पष्टीकरण है जावा जेनरिक और संग्रह  मॉरीस Naftalin, फिलिप Wadler द्वारा। इस पुस्तक की पुरजोर सिफारिश की जाती है। उद्धरण के लिए:

जावा में जेनेरिक टेम्पलेट्स जैसा दिखता है   सी ++। ... वाक्यविन्यास जानबूझकर है   समान और अर्थशास्त्र हैं   जानबूझकर अलग। ...   अर्थात्, जावा जेनेरिक हैं   मिटावट द्वारा परिभाषित, जहां सी ++ के रूप में   टेम्पलेट्स विस्तार से परिभाषित हैं।

कृपया पूर्ण स्पष्टीकरण पढ़ें यहाँ

alt text http://oreilly.com/catalog/covers/0596527756_cat.gif


13
2018-01-31 18:16





असल में, AFAIK, C ++ टेम्पलेट्स प्रत्येक प्रकार के लिए कोड की एक प्रति बनाते हैं, जबकि जावा जेनेरिक बिल्कुल उसी कोड का उपयोग करते हैं।

हाँ तुम कह सकते हैं कि सी ++ टेम्पलेट जावा जेनेरिक के बराबर है संकल्पना (हालांकि यह कहना उचित होगा कि जावा जेनरिक अवधारणा में सी ++ के बराबर हैं)

यदि आप सी ++ के टेम्पलेट तंत्र से परिचित हैं, तो आप सोच सकते हैं कि जेनेरिक समान हैं, लेकिन समानता सतही है। जेनेरिक प्रत्येक विशेषज्ञता के लिए एक नई कक्षा उत्पन्न नहीं करते हैं, न ही वे "टेम्पलेट मेटाप्रोग्रामिंग" की अनुमति देते हैं।

से: जावा जेनिक्स


3
2018-01-31 05:18





सी ++ टेम्पलेट्स का एक अन्य लाभ specilization है।

<typename T> T sum(T a, T b) { return a + b; }
<typename T> T sum(T* a, T* b) { return (*a) + (*b); }
Special sum(const Special& a, const Special& b) { return a.plus(b); }

अब, यदि आप पॉइंटर्स के साथ योग कहते हैं, तो दूसरी विधि को कॉल किया जाएगा, यदि आप गैर-पॉइंटर ऑब्जेक्ट्स के साथ योग कहते हैं तो पहली विधि कॉल की जाएगी, और यदि आप विशेष ऑब्जेक्ट्स के साथ sum () को कॉल करते हैं, तो तीसरा कॉल किया जाएगा। मुझे नहीं लगता कि जावा के साथ यह संभव है।


3
2017-09-03 15:23



हो सकता है क्योंकि जावा में पॉइंटर्स नहीं हैं .. !! क्या आप एक बेहतर उदाहरण के साथ समझा सकते हैं? - Bhavuk Mathur