java - जावा "पास-बाय-रेफरेंस" या "पास-बाय-वैल्यू" है?




methods parameter-passing (20)

मैंने हमेशा सोचा कि जावा पास-बाय-रेफरेंस था

हालांकि, मैंने कुछ ब्लॉग पोस्ट देखे हैं (उदाहरण के लिए, यह ब्लॉग ) जो दावा करते हैं कि यह नहीं है।

मुझे नहीं लगता कि मैं उनके द्वारा किए गए भेद को समझता हूं।

स्पष्टीकरण क्या है?


प्रतिनिधित्व करते समय संदर्भ हमेशा एक मान होता है, इससे कोई फर्क नहीं पड़ता कि आप किस भाषा का उपयोग करते हैं।

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

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

कोर के नीचे यह किसी भी भाषा में किसी भी भाषा का प्रतिनिधित्व किए बिना तकनीकी रूप से असंभव है (जब यह तुरंत मूल्य बन जाता है)।

आइए कहें कि हमारे पास एक वैरिएबल फू है, इसकी जगह 47 वें बाइट मेमोरी में है और इसका वैल्यू 5 है। हमारे पास एक और वैरिएबल रेफ 2 फ़ू है जो स्मृति में 223 वें बाइट पर है, और इसका मान 47 होगा। यह Ref2Foo तकनीकी चर हो सकता है , कार्यक्रम द्वारा स्पष्ट रूप से बनाया नहीं है। यदि आप किसी अन्य जानकारी के बिना 5 और 47 देख रहे हैं, तो आप केवल दो मान देखेंगे । यदि आप उन्हें संदर्भ के रूप में उपयोग करते हैं तो पहुंचने के लिए 5हमें यात्रा करना है:

(Name)[Location] -> [Value at the Location]
---------------------
(Ref2Foo)[223]  -> 47
(Foo)[47]       -> 5

इस तरह कूद-टेबल काम करते हैं।

अगर हम फू के मूल्य के साथ एक विधि / कार्य / प्रक्रिया को कॉल करना चाहते हैं, तो भाषा और इसके कई विधि आमंत्रण मोड के आधार पर, चर को विधि में पास करने के कुछ संभावित तरीके हैं:

  1. 5 को सीपीयू रजिस्टरों में से एक में कॉपी किया जाता है (यानी ईएक्स)।
  2. 5 ढेर के लिए PUSHD हो जाता है।
  3. 47 को सीपीयू रजिस्टरों में से एक में कॉपी किया जाता है
  4. 47 ढेर के लिए PUSHD।
  5. 223 को सीपीयू रजिस्टरों में से एक में कॉपी किया जाता है।
  6. 223 ढेर के लिए PUSHD हो जाता है।

किसी मान के ऊपर प्रत्येक मामले में - मौजूदा मान की एक प्रति - बनाई गई है, अब यह इसे संभालने के लिए प्राप्त करने की विधि तक है। जब आप विधि के अंदर "फू" लिखते हैं, तो इसे या तो ईएक्स से पढ़ा जाता है, या स्वचालित रूप से डिफ्रेंस किया जाता है , या डबल डिफ्रेंस किया जाता है, प्रक्रिया इस बात पर निर्भर करती है कि भाषा कैसे काम करती है और / या फू किस प्रकार का निर्देश देता है। यह डेवलपर से तब तक छिपा हुआ है जब तक कि वह dereferencing प्रक्रिया को circumvents। इसलिए संदर्भ एक मान है जब प्रतिनिधित्व किया जाता है, क्योंकि संदर्भ एक मान है जिसे संसाधित किया जाना चाहिए (भाषा स्तर पर)।

अब हमने विधि को फू पास कर दिया है:

  • यदि 1. और 2. यदि आप फू ( Foo = 9) बदलते हैं तो यह केवल स्थानीय दायरे को प्रभावित करता है क्योंकि आपके पास मूल्य की एक प्रति है। विधि के अंदर से हम यह भी निर्धारित नहीं कर सकते कि मूल फू कहाँ स्थित था।
  • यदि 3. और 4. मामले में आप डिफ़ॉल्ट भाषा संरचनाओं का उपयोग करते हैं और Foo ( Foo = 11) को बदलते हैं, तो यह वैश्विक रूप से Foo को बदल सकता है (भाषा पर निर्भर करता है, यानी जावा या पास्कल की procedure findMin(x, y, z: integer; var m : integer); )। हालांकि अगर भाषा आपको अव्यवस्था प्रक्रिया को बाधित करने की अनुमति देती है, तो आप 47कह सकते हैं 49। उस बिंदु पर फू को बदल दिया गया लगता है, क्योंकि आपने इसे स्थानीय पॉइंटर बदल दिया है। और यदि आप विधि ( Foo = 12) के अंदर इस फू को संशोधित करना चाहते हैं तो आप शायद प्रोग्राम (उर्फ सेगफॉल्ट) के निष्पादन को FUBAR करेंगे क्योंकि आप उम्मीद से अलग स्मृति को लिखेंगे, आप निष्पादन योग्य रखने के लिए निर्धारित क्षेत्र को भी संशोधित कर सकते हैं प्रोग्राम और इसके लिए लिखना चल रहा कोड संशोधित करेगा (फू अब नहीं है 47)। लेकिन फू का मूल्य47वैश्विक रूप से नहीं बदला, केवल विधि के अंदर एक, क्योंकि 47विधि के लिए एक प्रति भी था।
  • 5 और 6. मामले में यदि आप 223विधि के अंदर संशोधित करते हैं तो यह 3 या 4 के समान मेहेम बनाता है। (एक पॉइंटर, जो अब खराब मान को इंगित करता है, जिसे फिर से पॉइंटर के रूप में उपयोग किया जाता है) लेकिन यह अभी भी एक स्थानीय है समस्या, 223 की प्रतिलिपि बनाई गई थी । हालांकि यदि आप अव्यवस्था Ref2Foo(यानी 223) तक पहुंचने में सक्षम हैं , तो इंगित मूल्य तक पहुंचने और संशोधित करने के लिए 47, कहें 49, यह वैश्विक स्तर पर फू को प्रभावित करेगा , क्योंकि इस मामले में तरीकों की प्रतिलिपि मिली है 223लेकिन संदर्भ 47केवल एक बार मौजूद है, और इसे बदलना करने के लिए 49हर नेतृत्व करेंगे Ref2Fooएक गलत मान के लिए डबल-dereferencing।

महत्वहीन विवरणों पर नाइटपिकिंग, यहां तक ​​कि भाषाएं जो पास-दर-संदर्भ करती हैं, वे कार्यों को मूल्यों को पास कर देंगे, लेकिन उन कार्यों को पता है कि उन्हें इसे संदर्भित उद्देश्यों के लिए उपयोग करना है। यह पास-द-रेफरेंस-ए-वैल्यू प्रोग्रामर से सिर्फ छिपा हुआ है क्योंकि यह व्यावहारिक रूप से बेकार है और शब्दावली केवल पास-बाय-रेफरेंस है

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

तो संक्षेप में और जावा की अपनी शब्दावली में, जावा पास-बाय-वैल्यू है जहां मूल्य हो सकता है: या तो वास्तविक मूल्य या एक मान जो संदर्भ का प्रतिनिधित्व करता है ।


कंट्रास्ट दिखाने के लिए, निम्न C++ और Java स्निपेट की तुलना करें:

सी ++ में: नोट: खराब कोड - मेमोरी लीक! लेकिन यह बिंदु दर्शाता है।

void cppMethod(int val, int &ref, Dog obj, Dog &objRef, Dog *objPtr, Dog *&objPtrRef)
{
    val = 7; // Modifies the copy
    ref = 7; // Modifies the original variable
    obj.SetName("obj"); // Modifies the copy of Dog passed
    objRef.SetName("objRef"); // Modifies the original Dog passed
    objPtr->SetName("objPtr"); // Modifies the original Dog pointed to 
                               // by the copy of the pointer passed.
    objPtr = new Dog("newObjPtr");  // Modifies the copy of the pointer, 
                                   // leaving the original object alone.
    objPtrRef->SetName("objRefPtr"); // Modifies the original Dog pointed to 
                                    // by the original pointer passed. 
    objPtrRef = new Dog("newObjPtrRef"); // Modifies the original pointer passed
}

int main()
{
    int a = 0;
    int b = 0;
    Dog d0 = Dog("d0");
    Dog d1 = Dog("d1");
    Dog *d2 = new Dog("d2");
    Dog *d3 = new Dog("d3");
    cppMethod(a, b, d0, d1, d2, d3);
    // a is still set to 0
    // b is now set to 7
    // d0 still have name "d0"
    // d1 now has name "objRef"
    // d2 now has name "objPtr"
    // d3 now has name "newObjPtrRef"
}

जावा में,

public static void javaMethod(int val, Dog objPtr)
{
   val = 7; // Modifies the copy
   objPtr.SetName("objPtr") // Modifies the original Dog pointed to 
                            // by the copy of the pointer passed.
   objPtr = new Dog("newObjPtr");  // Modifies the copy of the pointer, 
                                  // leaving the original object alone.
}

public static void main()
{
    int a = 0;
    Dog d0 = new Dog("d0");
    javaMethod(a, d0);
    // a is still set to 0
    // d0 now has name "objPtr"
}

जावा में केवल दो प्रकार के गुजरने हैं: अंतर्निर्मित प्रकारों के मूल्य के आधार पर, और ऑब्जेक्ट प्रकारों के लिए सूचक के मूल्य से।


जावा हमेशा पास-दर-मूल्य होता है । दुर्भाग्य से, उन्होंने किसी ऑब्जेक्ट का स्थान "संदर्भ" कहने का निर्णय लिया। जब हम किसी ऑब्जेक्ट का मान पास करते हैं, तो हम इसका संदर्भ पारित कर रहे हैं। यह शुरुआती लोगों को भ्रमित कर रहा है।

यह इस प्रकार चलता है:

public static void main(String[] args) {
    Dog aDog = new Dog("Max");
    // we pass the object to foo
    foo(aDog);
    // aDog variable is still pointing to the "Max" dog when foo(...) returns
    aDog.getName().equals("Max"); // true
    aDog.getName().equals("Fifi"); // false 
}

public static void foo(Dog d) {
    d.getName().equals("Max"); // true
    // change d inside of foo() to point to a new Dog instance "Fifi"
    d = new Dog("Fifi");
    d.getName().equals("Fifi"); // true
}

aDog.getName() ऊपर दिए गए उदाहरण में अभी भी "Max" वापस आ जाएगा। ऑब्जेक्ट संदर्भ मूल्य द्वारा पारित किया गया है क्योंकि main से मूल्य aDog फ़ंक्शन foo में Dog "Fifi" साथ नहीं बदला जाता है। यदि इसे संदर्भ द्वारा पारित किया गया था, तो main में aDog.getName() कॉल करने के बाद कॉल के बाद "Fifi" लौटाएगा।

इसी तरह:

public static void main(String[] args) {
    Dog aDog = new Dog("Max");
    foo(aDog);
    // when foo(...) returns, the name of the dog has been changed to "Fifi"
    aDog.getName().equals("Fifi"); // true
}

public static void foo(Dog d) {
    d.getName().equals("Max"); // true
    // this changes the name of d to be "Fifi"
    d.setName("Fifi");
}

उपर्युक्त उदाहरण में, Fifi foo(aDog) पर कॉल करने के बाद कुत्ते का नाम है क्योंकि ऑब्जेक्ट का नाम foo(...) अंदर सेट किया गया था। d पर किए जाने वाले किसी भी ऑपरेशन ऐसे हैं कि, सभी व्यावहारिक उद्देश्यों के लिए, वे एक Dog पर ही किए जाते हैं (सिवाय इसके कि जब d को बदल दिया जाता है तो d = new Dog("Boxer") जैसे विभिन्न Dog उदाहरण को इंगित किया जाता है।


जावा हमेशा मूल्य से गुजरता है, बिना किसी अपवाद के।

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

तो, एक विधि बुलाते समय

  • आदिम तर्कों ( int , long , आदि) के लिए, मान द्वारा पास आदिम का वास्तविक मान है (उदाहरण के लिए, 3)।
  • वस्तुओं के लिए, मूल्य से गुजर वस्तु के संदर्भ का मूल्य है।

तो यदि आपने कुछ doSomething(foo) और public void doSomething(Foo foo) { .. } दो Foos ने संदर्भों की प्रतिलिपि बनाई है जो एक ही ऑब्जेक्ट को इंगित करती हैं।

स्वाभाविक रूप से, किसी ऑब्जेक्ट के संदर्भ में मूल्य से गुज़रना संदर्भ के आधार पर किसी ऑब्जेक्ट को पास करने (और अभ्यास से अलग करने योग्य) जैसा दिखता है।


मुझे लगता है कि "पास-बाय-रेफरेंस बनाम पास-बाय-वैल्यू" के बारे में बहस करना बहुत उपयोगी नहीं है।

यदि आप कहते हैं, "जावा पास-बाय-जो भी (संदर्भ / मान) है, किसी भी मामले में, आप एक पूर्ण उत्तर प्रदान नहीं कर रहे हैं। यहां कुछ अतिरिक्त जानकारी दी गई है जो उम्मीद में मदद करेंगे कि स्मृति में क्या हो रहा है।

जावा कार्यान्वयन से पहले ढेर / ढेर पर क्रैश कोर्स: एक कैफेटेरिया में प्लेटों के ढेर की तरह, एक अच्छी व्यवस्थित फैशन में मूल्य स्टैक पर और बंद होते हैं। ढेर में मेमोरी (गतिशील स्मृति के रूप में भी जाना जाता है) खतरनाक और असंगठित है। JVM बस जहां भी हो सकता है वहां स्थान पाता है, और इसे मुक्त करता है क्योंकि इसका उपयोग करने वाले चर की आवश्यकता नहीं होती है।

ठीक है। सबसे पहले, स्थानीय प्राइमेटिव ढेर पर जाते हैं। तो यह कोड:

int x = 3;
float y = 101.1f;
boolean amIAwesome = true;

इसके परिणाम:

जब आप किसी ऑब्जेक्ट को घोषित करते हैं और तत्काल करते हैं। वास्तविक वस्तु ढेर पर जाती है। ढेर पर क्या चल रहा है? ढेर पर वस्तु का पता। सी ++ प्रोग्रामर इसे एक पॉइंटर कहते हैं, लेकिन कुछ जावा डेवलपर्स "पॉइंटर" शब्द के खिलाफ हैं। जो कुछ। बस पता है कि वस्तु का पता ढेर पर चला जाता है।

इस तरह:

int problems = 99;
String name = "Jay-Z";

एक सरणी एक वस्तु है, इसलिए यह ढेर पर भी जाती है। और सरणी में वस्तुओं के बारे में क्या? उन्हें अपना हीप स्पेस मिलता है, और प्रत्येक ऑब्जेक्ट का पता सरणी के अंदर जाता है।

JButton[] marxBros = new JButton[3];
marxBros[0] = new JButton("Groucho");
marxBros[1] = new JButton("Zeppo");
marxBros[2] = new JButton("Harpo");

तो, जब आप कोई विधि कॉल करते हैं तो क्या हो जाता है? यदि आप किसी ऑब्जेक्ट में पास करते हैं, तो आप वास्तव में जो गुजर रहे हैं वह ऑब्जेक्ट का पता है। कुछ पते के "मूल्य" कह सकते हैं, और कुछ कहते हैं कि यह केवल वस्तु का संदर्भ है। यह "संदर्भ" और "मूल्य" समर्थकों के बीच पवित्र युद्ध की उत्पत्ति है। जिसे आप इसे कहते हैं उतना महत्वपूर्ण नहीं है जितना कि आप समझते हैं कि क्या हो रहा है वह वस्तु का पता है।

private static void shout(String name){
    System.out.println("There goes " + name + "!");
}

public static void main(String[] args){
    String hisName = "John J. Jingleheimerschmitz";
    String myName = hisName;
    shout(myName);
}

एक स्ट्रिंग बन जाती है और इसके लिए स्थान ढेर में आवंटित किया जाता है, और स्ट्रिंग पर पता स्टैक पर संग्रहीत किया जाता है और पहचानकर्ता hisName दिया जाता है, क्योंकि दूसरे स्ट्रिंग का पता पहले जैसा ही होता है, कोई नया स्ट्रिंग नहीं बनाया जाता है और कोई नया ढेर स्थान आवंटित नहीं किया गया है, लेकिन स्टैक पर एक नया पहचानकर्ता बनाया गया है। फिर हम shout() : एक नया स्टैक फ्रेम बनाया गया है और एक नया पहचानकर्ता, name बनाया गया है और पहले से मौजूद स्ट्रिंग का पता सौंपा गया है।

तो, मूल्य, संदर्भ? आप "आलू" कहते हैं।


मैंने अभी देखा है कि आपने मेरे लेख का संदर्भ दिया है।

जावा स्पेक का कहना है कि जावा में सबकुछ पास-बाय-वैल्यू है। जावा में "पास-बाय-रेफरेंस" जैसी कोई चीज़ नहीं है।

इसे समझने की कुंजी यह है कि कुछ ऐसा है

Dog myDog;

एक कुत्ता नहीं है; यह वास्तव में एक कुत्ते के लिए एक सूचक है।

इसका मतलब क्या है, जब आपके पास है

Dog myDog = new Dog("Rover");
foo(myDog);

आप अनिवार्य रूप से बनाई गई Dog ऑब्जेक्ट का पता foo विधि पर पास कर रहे हैं।

(मैं अनिवार्य रूप से कहता हूं क्योंकि जावा पॉइंटर्स प्रत्यक्ष पते नहीं हैं, लेकिन इस तरह उनके बारे में सोचना सबसे आसान है)

मान लीजिए कि Dog ऑब्जेक्ट मेमोरी एड्रेस 42 पर रहता है। इसका मतलब है कि हम विधि को 42 पास करते हैं।

अगर विधि को परिभाषित किया गया था

public void foo(Dog someDog) {
    someDog.setName("Max");     // AAA
    someDog = new Dog("Fifi");  // BBB
    someDog.setName("Rowlf");   // CCC
}

चलो देखते हैं कि क्या हो रहा है।

  • पैरामीटर कुछ someDog मूल्य 42 पर सेट है
  • लाइन "एएए" पर
    • कुछ Dog को Dog लिए इंगित किया जाता है (पता 42 पर Dog वस्तु)
    • वह Dog (पता 42 पर एक) को अपना नाम मैक्स में बदलने के लिए कहा जाता है
  • लाइन पर "बीबीबी"
    • एक नया Dog बनाया गया है। मान लीजिए कि वह 74 पर है
    • हम 74 को पैरामीटर कुछ someDog असाइन करते हैं
  • लाइन "सीसीसी" पर
    • कुछ Dog को Dog लिए इंगित किया जाता है (पता 74 पर Dog वस्तु)
    • वह Dog (पता 74 पर वाला एक) को अपना नाम रोवल में बदलने के लिए कहा जाता है
  • फिर, हम वापस आते हैं

अब चलिए सोचें कि विधि के बाहर क्या होता है:

क्या myDog बदल गया?

कुंजी है

ध्यान में रखते हुए कि myDog Dog एक सूचक है , न कि एक वास्तविक Dog , जवाब नहीं है। myDog अभी भी मूल्य 42 है; यह अभी भी मूल Dog को इंगित कर रहा है (लेकिन ध्यान दें कि "एएए" रेखा के कारण, इसका नाम अब "मैक्स" है - अभी भी वही कुत्ता; myDog का मान नहीं बदला है।)

पते का पालन करना और इसके अंत में क्या बदलना पूरी तरह से मान्य है; हालांकि, परिवर्तनीय नहीं बदलता है।

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

सी ++ में, एडा, पास्कल और अन्य भाषाएं जो पास-बाय-रेफरेंस का समर्थन करती हैं, आप वास्तव में पारित चर को बदल सकते हैं।

यदि जावा पास-बाय-रेफरेंस myDog था, तो हमने ऊपर परिभाषित foo विधि बदल दी होगी जहां myDog इंगित कर रहा था जब उसने बीबीबी पर कुछ someDog असाइन किया था।

संदर्भ पैरामीटर के बारे में सोचें कि वेरिएबल के लिए उपनाम के रूप में उपनाम हैं। जब वह उपनाम असाइन किया जाता है, तो वैरिएबल जो पास किया गया था।


जावा हमेशा मूल्य से गुजरता है, संदर्भ द्वारा पास नहीं होता है

सबसे पहले, हमें यह समझने की जरूरत है कि मूल्य से क्या पास है और संदर्भ द्वारा पास किया गया है।

मूल्य से गुजरने का मतलब है कि आप वास्तविक पैरामीटर के मान की स्मृति में प्रतिलिपि बना रहे हैं। यह वास्तविक पैरामीटर की सामग्री की एक प्रति है

संदर्भ द्वारा पास (जिसे पता द्वारा पास भी कहा जाता है) का अर्थ है कि वास्तविक पैरामीटर के पते की एक प्रति संग्रहित की जाती है

कभी-कभी जावा संदर्भ द्वारा पास का भ्रम दे सकता है। चलिए देखते हैं कि यह नीचे दिए गए उदाहरण का उपयोग करके कैसे काम करता है:

public class PassByValue {
    public static void main(String[] args) {
        Test t = new Test();
        t.name = "initialvalue";
        new PassByValue().changeValue(t);
        System.out.println(t.name);
    }

    public void changeValue(Test f) {
        f.name = "changevalue";
    }
}

class Test {
    String name;
}

इस कार्यक्रम का उत्पादन है:

changevalue

चलो कदम से कदम समझते हैं:

Test t = new Test();

जैसा कि हम सभी जानते हैं कि यह ढेर में एक वस्तु बनायेगा और संदर्भ मान को वापस टी पर वापस कर देगा। उदाहरण के लिए, मान लीजिए कि टी का मान है 0x100234(हम वास्तविक जेवीएम आंतरिक मूल्य नहीं जानते हैं, यह सिर्फ एक उदाहरण है)।

new PassByValue().changeValue(t);

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

यदि आप संदर्भ f का उपयोग कर फ़ंक्शन में कुछ भी बदलते हैं तो यह ऑब्जेक्ट की मौजूदा सामग्री को संशोधित करेगा। यही कारण है कि हमें आउटपुट मिला changevalue, जिसे फ़ंक्शन में अपडेट किया गया है।

इसे और अधिक स्पष्ट रूप से समझने के लिए, निम्न उदाहरण पर विचार करें:

public class PassByValue {
    public static void main(String[] args) {
        Test t = new Test();
        t.name = "initialvalue";
        new PassByValue().changeRefence(t);
        System.out.println(t.name);
    }

    public void changeRefence(Test f) {
        f = null;
    }
}

class Test {
    String name;
}

क्या यह फेंक देगा NullPointerException? नहीं, क्योंकि यह केवल संदर्भ की एक प्रति पास करता है। संदर्भ से गुज़रने के मामले में, यह NullPointerExceptionनीचे देखा गया है, जैसा कि नीचे देखा गया था:

उम्मीद है कि यह मदद करेगा।


यह आपको कुछ अंतर्दृष्टि देगा कि जावा वास्तव में इस बिंदु पर कैसे काम करता है कि जावा के संदर्भ में गुजरने या मूल्य से गुजरने के बारे में आपकी अगली चर्चा में आप केवल मुस्कान करेंगे :-)

चरण एक कृपया अपने दिमाग से मिटा दें कि शब्द 'पी' से शुरू होता है "_ _ _ _ _ _ _", खासकर अगर आप अन्य प्रोग्रामिंग भाषाओं से आते हैं। जावा और 'पी' को एक ही पुस्तक, फोरम, या यहां तक ​​कि txt में भी नहीं लिखा जा सकता है।

चरण दो याद रखें कि जब आप किसी ऑब्जेक्ट को किसी विधि में पास करते हैं तो आप ऑब्जेक्ट संदर्भ पास कर रहे हैं, न कि ऑब्जेक्ट स्वयं।

  • छात्र : मास्टर, क्या इसका मतलब यह है कि जावा पास-दर-संदर्भ है?
  • मास्टर : घास का मैदान, संख्या

अब सोचें कि ऑब्जेक्ट का संदर्भ / चर क्या करता है / है:

  1. एक वेरिएबल बिट्स रखता है जो जेवीएम को बताता है कि मेमोरी (हीप) में संदर्भित ऑब्जेक्ट को कैसे प्राप्त किया जाए।
  2. किसी विधि के लिए तर्क पारित करते समय आप संदर्भ चर को पार नहीं कर रहे हैं, लेकिन संदर्भ चर में बिट्स की एक प्रति । ऐसा कुछ: 3bad086a। 3bad086a पारित वस्तु को प्राप्त करने के लिए एक तरीका का प्रतिनिधित्व करता है।
  3. तो आप बस 3bad086a पास कर रहे हैं कि यह संदर्भ का मूल्य है।
  4. आप संदर्भ का मूल्य पारित कर रहे हैं, न कि संदर्भ स्वयं (और वस्तु नहीं)।
  5. यह मान वास्तव में कॉपी किया गया है और विधि को दिया गया है

निम्नलिखित में (कृपया इसे संकलित / निष्पादित करने का प्रयास न करें ...):

1. Person person;
2. person = new Person("Tom");
3. changeName(person);
4.
5. //I didn't use Person person below as an argument to be nice
6. static void changeName(Person anotherReferenceToTheSamePersonObject) {
7.     anotherReferenceToTheSamePersonObject.setName("Jerry");
8. }

क्या होता है?

  • परिवर्तनीय व्यक्ति लाइन # 1 में बनाया गया है और यह शुरुआत में शून्य है।
  • लाइन # 2 में स्मृति में संग्रहीत एक नया व्यक्ति ऑब्जेक्ट बनाया गया है, और परिवर्तनीय व्यक्ति को व्यक्ति ऑब्जेक्ट का संदर्भ दिया जाता है। यही है, इसका पता। मान लें 3bad086a।
  • ऑब्जेक्ट का पता धारण करने वाला परिवर्तनीय व्यक्ति लाइन # 3 में फ़ंक्शन पर भेज दिया जाता है।
  • लाइन # 4 में आप चुप्पी की आवाज सुन सकते हैं
  • लाइन # 5 पर टिप्पणी की जांच करें
  • एक विधि स्थानीय चर - anotherReferenceToTheSamePersonObject - बनाया गया है और फिर जादू # 6 में जादू आता है:
    • परिवर्तनीय / संदर्भ व्यक्ति को बिट-बाय-बिट की प्रतिलिपि बनाई जाती है और फ़ंक्शन के अंदर किसी अन्य संदर्भ में पारित किया जाता है।
    • व्यक्ति के कोई नए उदाहरण नहीं बनाए जाते हैं।
    • दोनों " व्यक्ति " और " anotherReferenceToTheSamePersonObject " 3bad086a के समान मान को पकड़ते हैं।
    • इसे आजमाएं लेकिन व्यक्ति == किसी अन्य संदर्भ के लिए TheSamePersonObject सत्य होगा।
    • दोनों चरों में संदर्भ की पहचान की प्रतियां हैं और वे दोनों एक ही व्यक्ति वस्तु, ढेर पर समान वस्तु और एक प्रतिलिपि नहीं देखते हैं।

एक तस्वीर एक हजार शब्दों के बराबर होती है:

ध्यान दें कि anotherReferenceToTheSamePersonObject तीर ऑब्जेक्ट की ओर निर्देशित है और परिवर्तनीय व्यक्ति की ओर नहीं!

अगर आपको यह नहीं मिला तो बस मुझ पर भरोसा करें और याद रखें कि यह कहना बेहतर है कि जावा मूल्य से गुजरता है । खैर, संदर्भ मूल्य से गुजरें । ओह ठीक है, यहां तक ​​कि पास-बाय-कॉपी-ऑफ-द-वेरिएबल-वैल्यू भी बेहतर है ! ;)

अब मुझे नफरत करने के लिए स्वतंत्र महसूस करें, लेकिन ध्यान दें कि यह देखते हुए विधि तर्कों के बारे में बात करते समय आदिम डेटा प्रकारों और ऑब्जेक्ट्स को पार करने के बीच कोई अंतर नहीं है।

आप हमेशा संदर्भ के मूल्य के बिट्स की एक प्रति पास करते हैं!

  • यदि यह एक आदिम डेटा प्रकार है तो इन बिट्स में आदिम डेटा प्रकार का मूल्य होगा।
  • यदि यह ऑब्जेक्ट है तो बिट्स में उस पते का मान होगा जो JVM को ऑब्जेक्ट को कैसे प्राप्त करें।

जावा पास-बाय-वैल्यू है क्योंकि किसी विधि के अंदर आप संदर्भित ऑब्जेक्ट को जितना चाहें उतना संशोधित कर सकते हैं, लेकिन इससे कोई फर्क नहीं पड़ता कि आप कितनी मेहनत करते हैं, आप कभी भी पारित चर को संशोधित करने में सक्षम नहीं होंगे जो संदर्भ रखेगा (पी _ _ _ नहीं _ _ _ _) वही वस्तु कोई फर्क नहीं पड़ता कि क्या!

उपरोक्त परिवर्तननाम फ़ंक्शन पारित संदर्भ की वास्तविक सामग्री (बिट मान) को संशोधित करने में सक्षम नहीं होगा। दूसरे शब्द में परिवर्तननाम व्यक्ति व्यक्ति को किसी अन्य वस्तु का संदर्भ नहीं दे सकता है।

बेशक आप इसे छोटा कर सकते हैं और बस कहें कि जावा पास-दर-मूल्य है!


कुछ पदों में कुछ सुधार।

सी संदर्भ द्वारा पास का समर्थन नहीं करता है। यह हमेशा मूल्य से गुजरता है। सी ++ संदर्भ द्वारा पास का समर्थन करता है, लेकिन डिफ़ॉल्ट नहीं है और यह काफी खतरनाक है।

इससे कोई फर्क नहीं पड़ता कि जावा में मूल्य क्या है: वस्तु का आदिम या पता (मोटे तौर पर), यह हमेशा मूल्य से गुजरता है।

यदि जावा ऑब्जेक्ट "व्यवहार करता है" जैसे कि संदर्भ द्वारा पारित किया जा रहा है, यह उत्परिवर्तन की एक संपत्ति है और पासिंग तंत्र के साथ बिल्कुल कुछ नहीं है।

मुझे यकीन नहीं है कि यह इतना भ्रमित क्यों है, शायद इसलिए कि बहुत सारे जावा "प्रोग्रामर" औपचारिक रूप से प्रशिक्षित नहीं होते हैं, और इस प्रकार यह समझ में नहीं आता कि वास्तव में स्मृति में क्या चल रहा है?


जावा मूल्य से एक कॉल है।

यह काम किस प्रकार करता है

  • आप हमेशा संदर्भ के मूल्य के बिट्स की एक प्रति पास करते हैं!

  • यदि यह एक आदिम डेटा प्रकार है, तो इन बिट्स में आदिम डेटा प्रकार का मान होता है, यही कारण है कि यदि हम विधि के अंदर हेडर के मान को बदलते हैं तो यह बाहर के परिवर्तनों को प्रतिबिंबित नहीं करता है।

  • यदि यह एक ऑब्जेक्ट डेटा प्रकार है जैसे Foo foo = new Foo () तो इस मामले में ऑब्जेक्ट के पते की प्रति फ़ाइल शॉर्टकट की तरह गुजरती है, मान लें कि हमारे पास C: \ डेस्कटॉप पर एक टेक्स्ट फ़ाइल abc.txt है और मान लीजिए कि हम शॉर्टकट बनाते हैं एक ही फ़ाइल और इसे C: \ desktop \ abc-shortcut के अंदर रखें ताकि जब आप C: \ desktop \ abc.txt से फ़ाइल तक पहुंचें और 'स्टैक ओवरफ़्लो' लिखें और फ़ाइल बंद करें और फिर आप शॉर्टकट से फ़ाइल खोलें तो आप लिखने के लिए प्रोग्रामर के लिए सबसे बड़ा ऑनलाइन समुदाय है ' तो कुल फ़ाइल परिवर्तन होगा ' स्टैक ओवरफ्लो प्रोग्रामर के लिए सबसे बड़ा ऑनलाइन समुदाय सीखने के लिए 'जिसका अर्थ यह है कि इससे कोई फर्क नहीं पड़ता कि आप फ़ाइल को खोलते हैं, हर बार जब हम एक ही फाइल तक पहुंच रहे थे, तो हम फू को एक फ़ाइल के रूप में मान सकते हैं और मान लें कि foo 123hd7h पर संग्रहीत है (मूल पता जैसे सी: \ डेस्कटॉप \ abc.txt ) पता और 234jdid (कॉपी किया गया पता जैसे सी: \ डेस्कटॉप \ abc-shortcut जिसमें वास्तव में फ़ाइल के मूल पते को शामिल किया गया है) .. तो बेहतर समझने के लिए शॉर्टकट फ़ाइल बनाएं और महसूस करें ...


नहीं, यह संदर्भ द्वारा पास नहीं है।

जावा भाषा विशिष्टता के अनुसार जावा मूल्य से गुजरता है:

जब विधि या कन्स्ट्रक्टर का आह्वान किया जाता है (§15.12), वास्तविक तर्क अभिव्यक्ति के मान विधि या कन्स्ट्रक्टर के शरीर के निष्पादन से पहले, घोषित प्रकार के प्रत्येक, नव निर्मित पैरामीटर चर , आरंभिक प्रारंभ करते हैं। DeclaratorId में दिखाई देने वाला पहचानकर्ता औपचारिक पैरामीटर को संदर्भित करने के लिए विधि या निर्माता के शरीर में एक साधारण नाम के रूप में उपयोग किया जा सकता है ।


मैंने सोचा कि मैं विनिर्देशों से अधिक विवरण जोड़ने के लिए इस उत्तर का योगदान दूंगा।

सबसे पहले, मूल्य बनाम संदर्भ बनाम गुजरने के बीच क्या अंतर है?

संदर्भ द्वारा उत्तीर्ण करने का अर्थ है बुलाए गए फ़ंक्शंस पैरामीटर कॉलर्स के उत्तीर्ण तर्क के समान होंगे (मूल्य नहीं, लेकिन पहचान - चर स्वयं)।

मूल्य से गुजरने का अर्थ है बुलाए गए फ़ंक्शंस पैरामीटर कॉलर्स के उत्तीर्ण तर्क की एक प्रति होगी।

या विकिपीडिया से, पास-दर-संदर्भ के विषय पर

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

और पास-दर-मूल्य के विषय पर

कॉल-दर-मूल्य में, तर्क अभिव्यक्ति का मूल्यांकन किया जाता है, और परिणामी मान फ़ंक्शन में संबंधित चर के लिए बाध्य होता है [...]। यदि फ़ंक्शन या प्रक्रिया इसके मानकों को मान असाइन करने में सक्षम है, तो केवल इसकी स्थानीय प्रति असाइन की गई है [...]।

दूसरा, हमें यह जानने की जरूरत है कि जावा अपनी विधि के इनवोकेशन में क्या उपयोग करता है। जावा भाषा विशिष्टता राज्यों

जब विधि या कन्स्ट्रक्टर का आह्वान किया जाता है (§15.12), वास्तविक तर्क अभिव्यक्ति के मान विधि या कन्स्ट्रक्टर के शरीर के निष्पादन से पहले, घोषित प्रकार के प्रत्येक, नव निर्मित पैरामीटर चर , आरंभिक प्रारंभ करते हैं।

इसलिए यह तर्क पैरामीटर चर के लिए तर्क के मान को निर्दिष्ट करता है (या बांधता है)।

तर्क का मूल्य क्या है?

आइए संदर्भ प्रकारों पर विचार करें, जावा वर्चुअल मशीन विशिष्टता राज्य

तीन प्रकार के संदर्भ प्रकार हैं : कक्षा प्रकार, सरणी प्रकार, और इंटरफ़ेस प्रकार। उनके मूल्य गतिशील रूप से बनाए गए वर्ग उदाहरण, सरणी, या कक्षा के उदाहरण या सरणी क्रमशः इंटरफेस को लागू करने के संदर्भ हैं।

जावा भाषा विशिष्टता भी कहा गया है

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

किसी तर्क का मान (कुछ संदर्भ प्रकार का) किसी ऑब्जेक्ट के लिए सूचक होता है। ध्यान दें कि एक चर, संदर्भ प्रकार रिटर्न प्रकार के साथ एक विधि का आविष्कार, और एक उदाहरण निर्माण अभिव्यक्ति ( new ...) सभी संदर्भ प्रकार मान को हल करते हैं।

इसलिए

public void method (String param) {}
...
String var = new String("ref");
method(var);
method(var.toString());
method(new String("ref"));

सभी Stringविधि के नव निर्मित पैरामीटर के उदाहरण के संदर्भ के मान को बाध्य करते हैं param। यह वही है जो पास-दर-मूल्य का वर्णन करता है। इस प्रकार, जावा पास-दर-मूल्य है

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

इसका आम तौर पर अर्थ यह है कि फ़ंक्शन तर्क के रूप में उपयोग किए जाने वाले चर को संशोधित कर सकता है (यानी असाइन करें) जो कुछ उसके कॉलर द्वारा देखा जाएगा।

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

जावा वर्चुअल मशीन स्पेसिफिकेशन में आदिम मान भी परिभाषित किए गए here । प्रकार का मान इसी अभिन्न या फ़्लोटिंग पॉइंट मान है, जो उचित रूप से एन्कोड किया गया है (8, 16, 32, 64, आदि बिट्स)।


इस मामले की जड़ यह है कि शब्द है संदर्भ अभिव्यक्ति "संदर्भ से गुजरती हैं" में कुछ शब्द का सामान्य अर्थ से पूरी तरह अलग है इसका मतलब संदर्भ जावा में।

जावा में आम तौर पर संदर्भ आ मतलब है एक वस्तु के संदर्भ में । लेकिन प्रोग्रामिंग भाषा सिद्धांत से संदर्भ / मूल्य द्वारा पारित तकनीकी शब्द वेरिएबल धारण करने वाले मेमोरी सेल के संदर्भ के बारे में बात कर रहे हैं , जो कुछ अलग है।


एक लंबी कहानी कम करने के लिए, Java ऑब्जेक्ट्स में कुछ बहुत ही विशिष्ट गुण हैं।

सामान्य तौर पर, जावा आदिम प्रकार (है int, bool, char, double, आदि) कि सीधे मूल्य द्वारा पारित कर रहे हैं। तब जावा में वस्तुएं होती हैं (जो कुछ भी निकलती है java.lang.Object)। ऑब्जेक्ट्स वास्तव में हमेशा एक संदर्भ के माध्यम से संभाले जाते हैं (संदर्भ एक संकेतक है जिसे आप स्पर्श नहीं कर सकते हैं)। इसका मतलब है कि असल में, वस्तुओं को संदर्भ द्वारा पारित किया जाता है, क्योंकि संदर्भ आम तौर पर दिलचस्प नहीं होते हैं। हालांकि इसका मतलब यह है कि आप यह नहीं बदल सकते कि किस ऑब्जेक्ट को इंगित किया गया है क्योंकि संदर्भ स्वयं मूल्य से गुजरता है।

क्या यह अजीब और भ्रमित लगता है? आइए मान लें कि कैसे सी लागू संदर्भ द्वारा पास किया जाता है और मूल्य से गुजरता है। सी में, डिफ़ॉल्ट सम्मेलन मूल्य से गुजरता है। void foo(int x)मूल्य से एक int पास करता है। void foo(int *x)एक ऐसा कार्य है जो एक नहीं चाहता है int a, लेकिन एक int के लिए एक सूचक foo(&a):। कोई &एक परिवर्तनीय पता पास करने के लिए ऑपरेटर के साथ इसका उपयोग करेगा ।

इसे सी ++ पर ले जाएं, और हमारे पास संदर्भ हैं। सन्दर्भ मूल रूप से (इस संदर्भ में) सिंटैक्टिक चीनी है जो समीकरण के सूचक भाग को छुपाता है: void foo(int &x)जिसे foo(a)संकलक स्वयं जानता है कि यह एक संदर्भ है और गैर संदर्भ का पता aपारित किया जाना चाहिए। जावा में, ऑब्जेक्ट्स का जिक्र करने वाले सभी वेरिएबल वास्तव में संदर्भ प्रकार के होते हैं, असल में दागदार नियंत्रण (और जटिलता) के बिना अधिकांश इरादे और उद्देश्यों के संदर्भ में कॉल को मजबूर करने के लिए, उदाहरण के लिए, सी ++।


जावा VALUE द्वारा मानकों को पास करता है, और केवल मूल्य से ।

लंबी कहानी को कम करने के लिए:

सी # से आने वाले लोगों के लिए: वहां कोई "आउट" पैरामीटर नहीं है।

पास्कल से आने वाले लोगों के लिए: कोई "var" पैरामीटर नहीं है

इसका मतलब है कि आप ऑब्जेक्ट से संदर्भ को नहीं बदल सकते हैं, लेकिन आप ऑब्जेक्ट की गुणों को हमेशा बदल सकते हैं।

एक वर्कअराउंड StringBuilderइसके बजाय पैरामीटर का उपयोग करना है String। और आप हमेशा सरणी का उपयोग कर सकते हैं!


जावा केवल मूल्य से गुजर चुका है। इसे प्रमाणित करने के लिए एक बहुत ही सरल उदाहरण।

public void test() {
    MyClass obj = null;
    init(obj);
    //After calling init method, obj still points to null
    //this is because obj is passed as value and not as reference.
}
private void init(MyClass objVar) {
    objVar = new MyClass();
}

जैसा कि कई लोगों ने पहले उल्लेख किया था, जावा हमेशा पास-दर-मूल्य होता है

यहां एक और उदाहरण है जो आपको अंतर को समझने में मदद करेगा ( क्लासिक स्वैप उदाहरण ):

public class Test {
  public static void main(String[] args) {
    Integer a = new Integer(2);
    Integer b = new Integer(3);
    System.out.println("Before: a = " + a + ", b = " + b);
    swap(a,b);
    System.out.println("After: a = " + a + ", b = " + b);
  }

  public static swap(Integer iA, Integer iB) {
    Integer tmp = iA;
    iA = iB;
    iB = tmp;
  }
}

प्रिंटों:

इससे पहले: ए = 2, बी = 3 के
बाद: ए = 2, बी = 3

ऐसा इसलिए होता है क्योंकि आईए और आईबी नए स्थानीय संदर्भ चर होते हैं जिनके पास पारित संदर्भों का समान मूल्य होता है (वे क्रमशः ए और बी को इंगित करते हैं)। इसलिए, आईए या आईबी के संदर्भों को बदलने की कोशिश केवल स्थानीय क्षेत्र में बदल जाएगी, न कि इस विधि के बाहर।


भेद, या शायद जिस तरह से मुझे याद है क्योंकि मैं मूल पोस्टर के समान प्रभाव के रूप में उपयोग करता था: जावा हमेशा मूल्य से गुजरता है। जावा में सभी ऑब्जेक्ट्स (जावा में, प्राइमेटिव्स को छोड़कर कुछ भी) संदर्भ हैं। ये संदर्भ मूल्य से पारित होते हैं।


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


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

public class PassByCopy{
    public static void changeName(Dog d){
        d.name = "Fido";
    }
    public static void main(String[] args){
        Dog d = new Dog("Maxx");
        System.out.println("name= "+ d.name);
        changeName(d);
        System.out.println("name= "+ d.name);
    }
}
class Dog{
    public String name;
    public Dog(String s){
        this.name = s;
    }
}

जावा PassByCopy का उत्पादन:

नाम = मैक्सएक्स
नाम = फिडो

आदिम रैपर वर्ग और स्ट्रिंग्स अपरिवर्तनीय हैं इसलिए उन प्रकारों का उपयोग करने वाला कोई भी उदाहरण अन्य प्रकार / वस्तुओं के समान काम नहीं करेगा।







pass-by-value