2013-08-03 7 views
26

एक विधि एक स्थानीय चर i हों तो:जावा प्राइमेटिव्स अपरिवर्तनीय हैं?

int i = 10; 

और उसके बाद मैं एक नया मान असाइन:

i = 11; 

यह एक नया स्मृति स्थान का आवंटन होगा? या बस मूल मूल्य को प्रतिस्थापित करें?

इसका मतलब यह है कि पुरातन अपरिवर्तनीय कर रहे हैं?

+0

यह स्मृति में नई जगह नहीं बनाएगा। – Maroun

+1

यह मूल को प्रतिस्थापित करेगा। जावा प्राइमेटिव ** ** ऑब्जेक्ट्स नहीं हैं। 'इंटेगर '(और अन्य आदिम रैपर वर्ग) ** ** अपरिवर्तनीय हैं। –

+3

@BrianRoach नहीं उसने नहीं किया। आपके तर्क से, स्ट्रिंग्स म्यूटेबल हैं: 'स्ट्रिंग स्ट्र = "टेस्ट"; str = "newStr"; '। ओपी के सवाल का जवाब देने के लिए, वे वास्तव में अपरिवर्तनीय हैं। यदि आप 'i ++' पर विचार करते हैं, तो यह वास्तव में है: 'i = i + 1'। जो आप देख सकते हैं वह 'i' का मान लेता है, एक जोड़ता है और इस नए मान पर' i' को फिर से सौंपता है। –

उत्तर

49

यह एक नया स्मृति स्थान का आवंटन होगा? या बस मूल मूल्य को प्रतिस्थापित करें?

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

लेकिन इसे एक तरफ सेट करना। । । अगर हम यहां अमूर्तता लेते हैं कि एक स्थानीय चर कॉल कॉल पर स्मृति स्थान को इंगित करता है, तो i = 11 उस स्मृति स्थान पर मान को संशोधित करेगा। इसे एक नए मेमोरी लोकेशन का उपयोग करने की आवश्यकता नहीं होगी, क्योंकि परिवर्तनीय i पुरानी जगह का जिक्र करने वाली एकमात्र चीज थी।

क्या इसका मतलब यह है कि प्राइमेटिव अपरिवर्तनीय हैं?

हाँ और नहीं: हाँ, प्राइमेटिव अपरिवर्तनीय हैं, लेकिन नहीं, यह उपरोक्त की वजह से नहीं है।

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

प्राइमेटिव के मामले में, उनके सभी गुण उनकी पहचान से पूरी तरह से निर्धारित होते हैं; 1 हमेशा 1 का मतलब है, कोई फर्क नहीं पड़ता कि, और 1 + 1 हमेशा 2 है। आप इसे बदल नहीं सकते।

एक दिया int चर मूल्य 1 है, तो आप के बजाय मूल्य 2 के लिए इसे बदल सकते हैं, लेकिन यह है कि पहचान की कुल परिवर्तन है: यह अब एक ही मूल्य यह पहले था है। यह मेरे बजाय किसी और को इंगित करने के लिए me बदलने जैसा है: यह वास्तव में मुझे में परिवर्तित नहीं करता है, यह केवल me बदलता है।

वस्तुओं के साथ

, ज़ाहिर है, आप अक्सर दोनों कर सकते हैं:

StringBuilder sb = new StringBuilder("foo"); 
sb.append("bar"); // mutate the object identified by sb 
sb = new StringBuilder(); // change sb to identify a different object 
sb = null; // change sb not to identify any object at all 

आम भाषा में, इन दोनों को "sb बदलते" के रूप में वर्णित किया जाएगा, क्योंकि लोगों को "sb" दोनों उल्लेख करने के लिए प्रयोग करेंगे परिवर्तनीय (जिसमें एक संदर्भ शामिल है) और ऑब्जेक्ट पर यह संदर्भित करता है (जब यह एक को संदर्भित करता है)। इस तरह की ढीलापन ठीक है, जब तक कि आप महत्वपूर्ण होने पर भेद को याद रखें।

+8

इसे व्यक्तिगत बनाने के लिए +1 – akf

+3

मैंने बाल बढ़ाए, लेकिन खेद है कि मैं एक बदले हुए आदमी हूं! – nawfal

6

Immutable का मतलब है हर बार और वस्तु के मूल्य में एक नया संदर्भ ढेर पर इसके लिए बनाई गई है बदल गया है कि। आप प्राचीन प्रकार के मामले में अपरिवर्तनीयता के बारे में बात नहीं कर सकते हैं, केवल रैपर वर्ग अपरिवर्तनीय हैं। जावा संदर्भ के अनुसार copy_by_value का उपयोग नहीं करता है।

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

उदाहरण के लिए, अगर आप 3 के मूल्य के साथ एक पूर्णांक चर गुजरती हैं, आप बिट्स का प्रतिनिधित्व 3.

एक बार एक आदिम घोषित किया गया है, its primitive type can never change की एक प्रति, गुजर रहे हैं, हालांकि अपने मूल्य बदल सकते हैं।

+0

@Maroun Maroun मैंने बस निम्नलिखित की कोशिश की: int i = 10; int j = i; सिसो (i); // 10 सिसो (जे); // 10 i = 11; syso (i) // 11 syso (जे) // 10 तो अगर मैं स्मृति में एक नई जगह का निर्माण नहीं करता है, तो कैसे j का मूल्य एक ही हो सकता है? – fYre

+0

जब आप i के मान को निर्दिष्ट करते हैं तो आदिम प्रकार के मामले में, मेरे मान के अनुरूप बिट्स की प्रतिलिपि बनाई जाती है, आप मेरे संदर्भ को निर्दिष्ट नहीं कर रहे हैं क्योंकि आप आदिम प्रकारों के संदर्भ में संदर्भ के बारे में बात नहीं कर सकते हैं। –

0

हां, वे अपरिवर्तनीय हैं। वे पूरी तरह से अपरिवर्तनीय हैं।

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

+1

नहीं, यह नहीं है। Primitives अपरिवर्तनीय हैं, चर नहीं हैं। – nes1983

+0

मैंने जवाब को गलत तरीके से पढ़ा;) मेरा बुरा .. देर से घंटा। – Maroun

2

यह एक पूर्ण उत्तर नहीं है, लेकिन यह प्राचीन प्रकार के मूल्यों की अपरिवर्तनीयता साबित करने का एक तरीका है।

तो आदिम मूल्यों (शाब्दिक) परिवर्तनशील हैं, तो निम्न कोड ठीक काम करेगा:

int i = 10; // assigned i the literal value of 10 
5 = i; // reassign the value of 5 to equal 10 
System.out.println(5); // prints 10 
बेशक

, यह सच नहीं है।

पूर्णांक मान, जैसे कि 5, 10 और 11 स्मृति में पहले ही संग्रहीत हैं। जब आप उनमें से एक के बराबर एक चर सेट करते हैं: यह स्मृति-स्लॉट में मान बदलता है जहां i है।

आप इस यहाँ निम्न कोड के लिए बाईटकोड के माध्यम से देख सकते हैं:

public void test(){ 
    int i = 10; 
    i = 11; 
    i = 10; 
} 

Bytecode:

// access flags 0x1 
public test()V 
L0 
    LINENUMBER 26 L0 
    BIPUSH 10 // retrieve literal value 10 
    ISTORE 1 // store it in value at stack 1: i 
L1 
    LINENUMBER 27 L1 
    BIPUSH 11 // same, but for literal value 11 
    ISTORE 1 
L2 
    LINENUMBER 28 L2 
    BIPUSH 10 // repeat of first set. Still references the same literal 10. 
    ISTORE 1 
L3 
    LINENUMBER 29 L3 
    RETURN 
L4 
    LOCALVARIABLE this LTest; L0 L4 0 
    LOCALVARIABLE i I L1 L4 1 
    MAXSTACK = 1 
    MAXLOCALS = 2 

आप बाईटकोड (उम्मीद) यह शाब्दिक मानों का संदर्भ (उदाहरण में देख सकते हैं : 10) और फिर इसे i परिवर्तनीय के लिए स्लॉट में संग्रहीत करता है। जब आप i के मान को बदलते हैं, तो आप बस उस स्लॉट में कौन सा मान संग्रहीत कर रहे हैं बदल रहे हैं। मूल्य स्वयं बदल नहीं रहे हैं, उनका स्थान है।

संबंधित मुद्दे