2011-04-06 13 views
74

मैं जानता हूँ कि यह शायद बहुत बेवकूफ है, लेकिन स्थानों में से एक बहुत कुछ का दावा है कि जावा में पूर्णांक वर्ग अपरिवर्तनीय है, फिर भी निम्नलिखित कोड है:पूर्णांक अपरिवर्तनीय

Integer a=3; 
Integer b=3; 
a+=b; 
System.out.println(a); 

किसी भी दे रही परेशानी के बिना पर क्रियान्वित (उम्मीद) परिणाम 6. तो प्रभावी ढंग से एक का मूल्य बदल गया है। इसका मतलब यह नहीं है कि इंटीजर उत्परिवर्तनीय है? माध्यमिक प्रश्न और थोड़ा ऑफटॉपिक: "अपरिवर्तनीय कक्षाओं को कॉपी कन्स्ट्रक्टर की आवश्यकता नहीं है"। किसी को भी समझाने की परवाह क्यों है?

+12

कक्षा अपरिवर्तनीय है, लेकिन ऑटोबॉक्सिंग फंकी चीजें होती जा रही है: http://stackoverflow.com/questions/3085332/comparison-between-variables-pointing-to-same-integer-object – birryree

+0

धन्यवाद, मुक्केबाजी कीवर्ड था मुझे google की आवश्यकता है :) –

+6

आप अंतिम या स्थिर मूल्य के साथ अपरिवर्तनीय भ्रमित हैं। –

उत्तर

77

अपरिवर्तनीय यह नहीं है कि a कभी भी किसी अन्य मान के बराबर नहीं हो सकता है। उदाहरण के लिए, String भी अपरिवर्तनीय है, लेकिन मैं अभी भी यह कर सकते हैं:

String str = "hello"; 
// str equals "hello" 
str = str + "world"; 
// now str equals "helloworld" 

तो क्या वहाँ क्या हुआ? चूंकि String अपरिवर्तनीय है, स्पष्ट रूप से str नहीं बदला गया था। लेकिन अब यह कुछ अलग है। ऐसा इसलिए है क्योंकि str अब एक पूरी तरह से नया तत्काल ऑब्जेक्ट है, जैसे आपका Integer है। तो a का मान उत्परिवर्तित नहीं हुआ, लेकिन इसे एक पूरी तरह से नई वस्तु के साथ बदल दिया गया, यानी new Integer(6)

+11

"ऐसा इसलिए है क्योंकि str अब पूरी तरह से नई तत्काल वस्तु है"। या, बल्कि, एक नई वस्तु के लिए str (एक varibale) _points_। ऑब्जेक्ट स्वयं म्यूटेबल नहीं है, लेकिन चूंकि चर अंतिम नहीं है, यह एक अलग ऑब्जेक्ट को इंगित कर सकता है। – Sandman

+0

हां, यह एक अलग वस्तु को इंगित करता है जिसे '+ =' ऑपरेशन के परिणामस्वरूप तत्काल किया गया था। –

+9

कड़ाई से बोलते हुए, यह * एक * नई * वस्तु नहीं होना चाहिए। बॉक्सिंग 'Integer.valueOf (int)' का उपयोग करता है और वह विधि 'इंटेगर' ऑब्जेक्ट्स के कैश को बनाए रखती है। तो 'इंटेगर' वैरिएबल पर '+ =' का परिणाम एक ऑब्जेक्ट हो सकता है जो पहले अस्तित्व में था (या यह एक ही ऑब्जेक्ट भी हो सकता है ... 'a + = 0' के मामले में)। –

41

a कुछ पूर्णांक (3) करने के लिए एक "संदर्भ" है, अपने आशुलिपि a+=b वास्तव में ऐसा करने का अर्थ है:

a = new Integer(3 + 3) 

तो नहीं, पूर्णांकों नहीं परिवर्तनशील हैं, लेकिन है कि उन्हें को इंगित चर हैं *।

* अपरिवर्तनीय चर होना संभव है, इन्हें कीवर्ड final द्वारा दर्शाया गया है, जिसका अर्थ है कि संदर्भ नहीं बदला जा सकता है।

final Integer a = 3; 
final Integer b = 3; 
a += b; // compile error, the variable `a` is immutable, too. 
3

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

अपने लिए यह समझने के लिए, लूप में पूर्णांक असाइनमेंट करें (लूप के बाहर घोषित पूर्णांक के साथ) और स्मृति में लाइव ऑब्जेक्ट्स को देखें।

कारण अपरिवर्तनीय वस्तुओं के लिए प्रतिलिपि बनाने की आवश्यकता नहीं है सामान्य सामान्य ज्ञान है। चूंकि प्रत्येक असाइनमेंट एक नई वस्तु बनाता है, इसलिए भाषा तकनीकी रूप से पहले से ही एक प्रतिलिपि बनाता है, इसलिए आपको दूसरी प्रतिलिपि बनाने की आवश्यकता नहीं है।

4

हाँ इंटीजर अपरिवर्तनीय है।

ए एक संदर्भ है जो किसी ऑब्जेक्ट को इंगित करता है। जब आप एक + = 3 चलाते हैं, तो एक अलग मान के साथ, एक नई इंटीजर ऑब्जेक्ट को संदर्भित करने के लिए ए को पुनः निर्दिष्ट करता है।

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

वस्तुओं और संदर्भों के बीच अंतर के बारे में पढ़ें here

2

"अपरिवर्तनीय कक्षाओं को कॉपी कन्स्ट्रक्टर की आवश्यकता नहीं है"। किसी को भी समझाने की परवाह क्यों है?

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

वहाँ कुछ अंतर्निहित मान्यताओं हालांकि इस प्रकार हैं:

  • यह मान लिया गया है कि आपके आवेदन वर्ग के उदाहरण का उद्देश्य पहचान पर कोई अर्थ जगह नहीं है।

  • यह मानता है कि कक्षा equals और hashCode अधिभारित हो गई है ताकि एक उदाहरण की एक प्रति "मूल के समान" हो ... इन तरीकों के अनुसार।

या तो या उन मान्यताओं के दोनों झूठा हो सकता है, और कहा कि एक प्रति निर्माता के अलावा वारंट सकता है।

16

आप निर्धारित कर सकते है कि वस्तु System.identityHashCode() का उपयोग कर बदल गया है (एक बेहतर तरीका उपयोग करने के लिए है सादा == लेकिन इसकी के रूप में स्पष्ट नहीं है कि संदर्भ के बजाय मूल्य बदल गया है)

Integer a = 3; 
System.out.println("before a +=3; a="+a+" id="+Integer.toHexString(System.identityHashCode(a))); 
a += 3; 
System.out.println("after a +=3; a="+a+" id="+Integer.toHexString(System.identityHashCode(a))); 

प्रिंट

before a +=3; a=3 id=70f9f9d8 
after a +=3; a=6 id=2b820dda 

आप ऑब्जेक्ट a के अंतर्निहित "आईडी" को देख सकते हैं जो बदल गया है।

+0

सिस्टम.identityHashCode() एक बहुत अच्छी टिप है। इसके लिए धन्यवाद। –

9

पूछा प्रारंभिक सवाल करने के लिए,

Integer a=3; 
Integer b=3; 
a+=b; 
System.out.println(a); 

पूर्णांक अपरिवर्तनीय है, तो क्या इसके बाद के संस्करण हो गया है है 'एक' मूल्य 6. का एक नया संदर्भ प्रारंभिक मूल्य 3 में कोई संदर्भ के साथ छोड़ दिया है करने के लिए बदल गया है स्मृति (यह बदला नहीं गया है), इसलिए यह कचरा इकट्ठा किया जा सकता है।

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

0

मैं स्पष्ट कर सकते हैं कि पूर्णांक (और फ्लोट की तरह अपने धर्म के अन्य, लघु आदि) सरल नमूना कोड से अडिग हैं:

नमूना कोड

public class Test{ 
    public static void main(String... args){ 
     Integer i = 100; 
     StringBuilder sb = new StringBuilder("Hi"); 
     Test c = new Test(); 
     c.doInteger(i); 
     c.doStringBuilder(sb); 
     System.out.println(sb.append(i)); //Expected result if Integer is mutable is Hi there 1000 
    } 

    private void doInteger(Integer i){ 
     i=1000; 
    } 

    private void doStringBuilder(StringBuilder sb){ 
     sb.append(" there"); 
    } 

} 

वास्तविक परिणाम

परिणाम आता है वह हाय वहाँ 100 अपेक्षित परिणाम के बजाय (दोनों sb के मामले में और मैं परिवर्तनशील वस्तुओं जा रहा है) हाय वहाँ 1000

यह मुख्य में मैं द्वारा बनाई गई वस्तु से पता चलता संशोधित नहीं है , जबकि एसबी संशोधित है।

तो स्ट्रिंगबिल्डर ने उत्परिवर्तनीय व्यवहार का प्रदर्शन किया लेकिन इंटीजर नहीं।

तो इंटीजर अपरिवर्तनीय है।इसलिए साबित कर दिया

एक और केवल पूर्णांक के बिना कोड:

public class Test{ 
    public static void main(String... args){ 
     Integer i = 100; 
     Test c = new Test(); 
     c.doInteger(i); 
     System.out.println(i); //Expected result is 1000 in case Integer is mutable 
    } 

    private void doInteger(Integer i){ 
     i=1000; 
    } 


} 
+0

आप दो अलग-अलग चीजें कर रहे हैं - पूर्णांक को पुन: असाइन करने और स्ट्रिंगबिल्डर पर एक विधि को कॉल करने का प्रयास कर रहे हैं। यदि आप 'निजी शून्य डूस्ट्रिंगबिल्डर (स्ट्रिंगबिल्डर एसबी) {एसबी = नया स्ट्रिंगबिल्डर(); } 'फिर 'एसबी' अपरिवर्तित है। – MT0

+0

मैंने स्ट्रिंगबिल्डर (जो म्यूटेबल है) को जोड़ा है जो कि एक दूसरे ऑब्जेक्ट के साथ इंटेगर को जस्टैक्टोज़ करने के लिए है। यदि आप चाहते हैं कि आप सभी स्ट्रिंगबिल्डर संबंधित कोड को हटा सकते हैं और 100 को देखने के लिए सिर्फ प्रिंटआउट I देख सकते हैं। –

+0

@ MT0 ने आपके संदर्भ के लिए न्यूनतम कोड जोड़ा। –

0

यह मैं कैसे समझ में है अपरिवर्तनीय

int a=3;  
int b=a; 
b=b+5; 
System.out.println(a); //this returns 3 
System.out.println(b); //this returns 8 

पूर्णांक उत्परिवर्तित सकता है, "एक" प्रिंट होगा 8 लेकिन ऐसा इसलिए नहीं है क्योंकि यह अपरिवर्तनीय है, यही कारण है कि यह 3 है। आपका उदाहरण सिर्फ एक ne है डब्ल्यू असाइनमेंट।

-1
public static void main(String[] args) { 
    // TODO Auto-generated method stub 

    String s1="Hi"; 
    String s2=s1; 

    s1="Bye"; 

    System.out.println(s2); //Hi (if String was mutable output would be: Bye) 
    System.out.println(s1); //Bye 

    Integer i=1000; 
    Integer i2=i; 

    i=5000; 

    System.out.println(i2); // 1000 
    System.out.println(i); // 5000 

    int j=1000; 
    int j2=j; 

    j=5000; 

    System.out.println(j2); // 1000 
    System.out.println(j); // 5000 


    char c='a'; 
    char b=c; 

    c='d'; 

    System.out.println(c); // d 
    System.out.println(b); // a 
} 

आउटपुट है:

हाय अलविदा घ एक

तो चार है परिवर्तनशील, स्ट्रिंग पूर्णांक और पूर्णांक अपरिवर्तनीय हैं।

+0

यह उत्तर दूसरों से कोई जानकारी प्रदान नहीं करता है। –

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