एक जावा पॉइंटर से जावा संदर्भ कैसे अलग है?


97

C में पॉइंटर्स हैं और Java में रेफरेंस कहा जाता है। उनके पास सामान्य अर्थों में कुछ चीजें हैं जो वे किसी चीज की ओर इशारा करते हैं। मुझे पता है कि सी में संकेत उन पतों को संग्रहीत करते हैं जो वे इंगित करते हैं। क्या संदर्भ भी पते को संग्रहीत करते हैं? वे कैसे भिन्न होते हैं सिवाय इसके कि सूचक अधिक लचीला और त्रुटि-प्रवण होता है?


10
नोट C ++ में ऐसे संदर्भ भी होते हैं जो संकेत या जावा संदर्भ से भिन्न होते हैं
jk।

@jk। मैंने सोचा था कि यह जावा के समान ही होगा। क्या अंतर है?
गिन्नुजॉज

17
C ++ संदर्भ विद्रोही नहीं हैं (अर्थात आप निर्दिष्ट ऑब्जेक्ट को बदल नहीं सकते हैं) और अशक्त नहीं हैं (यानी आप उन्हें वैध रूप से कोई वस्तु नहीं दे सकते हैं)।
एपीग्रामग्राम

@Gnijuohz ने कहा कि @AProgrammer ने क्या कहा: finalजावा में एक संदर्भ लगभग C ++ संदर्भ के बराबर है। कारण यह है कि वे बिल्कुल समतुल्य नहीं हैं , C ++ संदर्भ अतिरिक्त रूप से अशक्त नहीं है, जबकि finalजावा में एक संदर्भ अशक्त है।
उत्कु

जवाबों:


142

पते को संग्रहीत करके संदर्भ लागू किया जा सकता है। आमतौर पर जावा संदर्भों को संकेत के रूप में लागू किया जाएगा, लेकिन विनिर्देश द्वारा इसकी आवश्यकता नहीं है। वे आसान कचरा संग्रह को सक्षम करने के लिए अप्रत्यक्ष की एक अतिरिक्त परत का उपयोग कर सकते हैं। लेकिन अंत में यह (लगभग हमेशा) (सी-शैली) संकेत (जावा-शैली) संदर्भों के कार्यान्वयन में शामिल होने के लिए नीचे उबाल होगा।

आप संदर्भों के साथ सूचक अंकगणित नहीं कर सकते। सी में एक पॉइंटर और जावा में एक संदर्भ के बीच सबसे महत्वपूर्ण अंतर यह है कि आप वास्तव में जावा में एक संदर्भ के अंतर्निहित मूल्य को प्राप्त (और हेरफेर) नहीं कर सकते हैं। दूसरे शब्दों में: आप सूचक अंकगणित नहीं कर सकते।

सी में आप एक पॉइंटर (यानी पता) में कुछ जोड़ सकते हैं या कुछ चीजों को इंगित करने के लिए कुछ "घटित" कर सकते हैं जो "पास" हैं या उन स्थानों पर इंगित करें जो किसी भी स्थान पर हैं।

जावा में, एक संदर्भ केवल एक चीज और उस चीज की ओर इशारा करता है। आप एक वैरिएबल होल्ड को एक अलग संदर्भ बना सकते हैं , लेकिन आप इसे "मूल चीज़ के बाद की बात" को इंगित करने के लिए नहीं कह सकते।

संदर्भ दृढ़ता से टाइप किए गए हैं। एक और अंतर यह है कि जावा में एक पॉइंटर के प्रकार की तुलना में संदर्भ का प्रकार बहुत अधिक सख्ती से नियंत्रित किया जाता है। सी में आप इसे एक स्थान पर रख सकते हैं int*और char*उस स्थान पर मेमोरी को फिर से व्याख्या कर सकते हैं । यही कारण है कि फिर से व्याख्या जावा में काम नहीं करता है: यदि आप केवल कुछ यह है कि के रूप में संदर्भ के दूसरे छोर पर वस्तु की व्याख्या कर सकते पहले से ही है (यानी आप एक डाल सकता Objectके संदर्भ Stringसंदर्भ केवल तभी वस्तु बताया वास्तव में एक है करने के लिए String)।

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


18
+1 हो सकता है । कार्यान्वयन विवरणों पर भरोसा न करें।
बजे एक CVn

2
+1 कचरा संग्रहण एक विशिष्ट साहसिक बिंदु के रूप में उल्लेख के लायक नहीं है? यह एक और तरीका है कि सी पॉइंटर्स अधिक शक्तिशाली हैं, लेकिन इससे भी अधिक खतरनाक हैं (मुक्त करने के लिए झूलने वाले पॉइंटर्स का खतरा, स्मृति भ्रष्टाचार का कारण बनता है, मेमोरी लीक का खतरा)
MarkJ

संदर्भ और संकेत के बीच एक और अंतर यह है कि C में एक पॉइंटर को संख्याओं के अनुक्रम में बदला जा सकता है (जैसे कि memcpyएक को स्थानांतरित करने के लिए char[]) और इसके विपरीत। यदि एक पॉइंटर को संख्याओं के अनुक्रम में बदल दिया जाता है, जो कहीं पर संग्रहीत होता है (शायद स्क्रीन पर दिखाया गया है और कागज की एक पर्ची पर ऑपरेटर द्वारा कॉपी किया गया है), कंप्यूटर के भीतर पॉइंटर की सभी प्रतियां नष्ट हो जाती हैं, और संख्याओं का वह क्रम परिवर्तित हो जाता है एक पॉइंटर पर वापस (शायद ऑपरेटर द्वारा टाइप किए जाने के बाद), पॉइंटर को अभी भी उसी चीज़ को इंगित करना होगा जो उसने पहले किया था। एक कार्यक्रम जो ...
सुपरकैट

... एक सूचक को संख्याओं के रूप में प्रदर्शित किया, और फिर मैन्युअल रूप से दर्ज किए गए संख्याओं को एक सूचक में बदल दिया, "दुष्ट" हो सकता है, लेकिन यह किसी भी अपरिभाषित व्यवहार को तब तक लागू नहीं करेगा जब तक कि ऑपरेटर संख्याओं में टाइप नहीं किया गया था जो एक वैध बनाने के लिए नहीं दिखाया गया था। सूचक। सामान्य प्रयोजन के कचरा संग्रह इस प्रकार पूरी तरह से पोर्टेबल सी में असंभव है, क्योंकि कोई रास्ता नहीं है कि कंप्यूटर यह जान सकता है कि ब्रह्मांड में कहीं सूचक की एक प्रति मौजूद हो सकती है या नहीं।
सुपरकैट

जेएलएस, §4.3.1 के अनुसार, जावा में संदर्भ पॉइंटर्स हैं, इसलिए "आमतौर पर जावा संदर्भों को पॉइंटर्स के रूप में लागू किया जाएगा, लेकिन विनिर्देश द्वारा इसकी आवश्यकता नहीं है।" गलत है।
ल्यू बलोच

8

C ++ संदर्भ फिर से अलग हैं।

उन्हें आरंभीकृत किया जाना है और अशक्त नहीं किया जा सकता है (कम से कम एक अच्छी तरह से गठित कार्यक्रम में नहीं) और किसी और चीज़ का संदर्भ देने के लिए उन्हें बचाया नहीं जा सकता है। C ++ संदर्भ एक वस्तु के लिए एक उपनाम की तरह बहुत अधिक है।

पॉइंटर्स और जावा / सी ++ संदर्भों के बीच एक और महत्वपूर्ण अंतर यह है कि आप एक पॉइंटर का पता ले सकते हैं जिसे आप एक संदर्भ के पते तक नहीं पहुंचा सकते हैं (वास्तव में एक सी ++ संदर्भ वास्तव में स्मृति में एक वस्तु के रूप में मौजूद नहीं है) परिणामस्वरूप आप हो सकते हैं एक पॉइंटर को पॉइंटर लेकिन एक संदर्भ के लिए संदर्भ नहीं


4

जावा सन्दर्भ और सी पॉइंटर्स बिल्कुल दो बिंदुओं में भिन्न होते हैं:

  1. पूर्व के लिए कोई सूचक-अंकगणित नहीं है।
  2. और आप जो भी चाहते हैं, उसके लिए एक जावा संदर्भ नहीं बना सकते हैं, आप केवल उन लोगों को सहेज सकते हैं जो कहीं सुलभ (स्थिर क्षेत्र, वस्तुओं के क्षेत्र, स्थानीय चर) या फ़ंक्शन-इनवोकेशन (जैसे कंस्ट्रक्टर-कॉल) द्वारा लौटाए गए हैं, जो इस प्रकार सभी जावा को संदर्भित करते हैं ऑब्जेक्ट्स (कभी भी बुनियादी प्रकार जैसे संदर्भ char, intऔर इसी तरह)।

किसी ने लिखा है कि संदर्भ दृढ़ता से, आपके द्वारा लिखा गया है क्योंकि आपने ऐसे इलाज के लिए संकलक बाध्य नहीं कर सकता int*एक के रूप में char*
पूरी तरह से तथ्य यह है कि है कि एक तरफ से विशेष रूप से वास्तव में रूपांतरण है सुरक्षित , वहाँ सी में कोई बहुरूपता है, ताकि तुलना एक गैर स्टार्टर है।
निश्चित रूप से, जावा सी की तुलना में अधिक दृढ़ता से टाइप किया गया है, यह नहीं कि सी पॉइंटर्स बनाम जावा संदर्भों की एक विशेषता है, आपको टाइप-सेफ्टी (जेनेरिक प्रतिबंधों की अवहेलना से अलग) को तोड़ने के लिए जेएनआई का उपयोग करने की आवश्यकता है, लेकिन सी में भी आपको मजबूर करना होगा संकलक।

किसी ने लिखा है कि जावा संदर्भों को सी पॉइंटर्स के रूप में लागू किया जा सकता है, जिसके बारे में मुझे यकीन है, क्योंकि वे कड़ाई से कम शक्तिशाली हैं, 32 बिट मशीनों पर वे आम तौर पर होते हैं, अगर जेवीएम सी में लागू किया जाता है । हालांकि 64 बिट मशीनों पर, वे सामान्य रूप से साधारण ऑब्जेक्ट-पॉइंटर्स ("संपीड़ित ओओपी") को अंतरिक्ष और बैंडविड्थ को बचाने के लिए संकुचित करते हैं।
वैसे भी, उन सी पॉइंटर्स को हार्डवेयर पतों के बराबर होने की आवश्यकता नहीं है, भले ही वे आमतौर पर (> 99% कार्यान्वयन) प्रदर्शन कारणों से हों।
अंत में, यह एक कार्यान्वयन विवरण है जो प्रोग्रामर के संपर्क में नहीं है।


-1

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

निम्नलिखित जावा कोड पर विचार करें

public static void changeRValue(StringBuffer sb){
    sb = new StringBuffer("helllllo"); /*attempt to assign the reference
                                        to a new object*/
}
public static void main(String[] args) {
    StringBuffer sb = new StringBuffer("hi");     //Create a new string buffer
    changeRValue(sb);                             //Call changeRValue
    System.out.println(sb.toString());            //Prints "hi" not "hello"
}

अब c ++ में एक पॉइंटर पर विचार करें:

void func(Dog* dog){
    *dog = Dog("hello world"); //Change the value of dog to a new object
}

int main(int argc, const char * argv[]) {
    Dog dog1("hi");                            //Create a dog object
    func(&dog1);                               //pass the address of dog
    cout << dog1.name;                         //Prints "hello world" not hi.
    return 0;
}

मैंने सोचा कि मैं इसे जोड़ सकता हूं कि इसे एक
कास्ट

2
आप जावा में इंगित ऑब्जेक्ट को C ++ की तरह ही आसानी से संशोधित कर सकते हैं। आपको बस सही सदस्यों तक पहुंच की आवश्यकता है। जावा ऑब्जेक्ट में असाइनमेंट-ऑपरेटर नहीं हैं क्योंकि जावा उपयोगकर्ता-परिभाषित ऑपरेटर-ओवरलोडिंग का समर्थन नहीं करता है, इसलिए आप एक अतिभारित ऑपरेटर, बड़े सौदे का उपयोग नहीं कर सकते हैं। जावा की कमी का इस तथ्य से कोई लेना-देना नहीं है कि जावा संदर्भ पॉइंटर-एरीमेट्रिक के सी ++ पॉइंटर्स बेरफ्ट के समान हैं।
Deduplicator
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.