2012-10-27 12 views
29

मैं समझ नहीं पा रहा हूं कि इंटीजर के लिए जावा कॉन्स्टेंट पूल कैसे काम करता है।इंटीजर निरंतर पूल का व्यवहार 127 पर क्यों बदलता है?

मैं स्ट्रिंग्स के व्यवहार को समझता हूं, और इसलिए खुद को औचित्य देने में सक्षम हूं कि यह इंटीजर कॉन्स्टेंट्स के साथ भी वही मामला है।

तो, पूर्णांकों

Integer i1 = 127; 
Integer i2 = 127; 
System.out.println(i1==i2); // True 

&

Integer i1 = new Integer(127); 
Integer i2 = new Integer(127); 
System.out.println(i1==i2); // False 

यहाँ तक के लिए सब कुछ मेरे सिर में चला जाता है।

क्या मैं पचाने के लिए है नहीं पा रहा हूँ, इसे दूसरे तरीके से व्यवहार करने के तरीके मैं यह व्यवहार परिवर्तन 127 के बाद 127 से पूर्णांक बढ़ाने के लिए, नीचे दिए गए कोड छोटा सा अंश है

Integer i1 = 128; 
Integer i2 = 128; 
System.out.println(i1==i2); // False. WHY????? 

किसी मदद कर सकते हैं मुझे इस बात को समझ?

+0

देखने http://stackoverflow.com/questions/1700081/why-does-128-128-return-false-but-127-127-return-true-when-converting-to Inteter.valueOf() का उल्लेख करने के लिए -integ? lq = 1 –

उत्तर

35

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

int x = 10; 
int y = x + 1; 
Integer z = y; // Not a compile-time constant! 
Integer constant = 11; 
System.out.println(z == constant); // true; reference comparison 

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

ध्यान दें कि हालांकि यह गारंटी नहीं है, हर कार्यान्वयन मैं का उपयोग करता है Integer.valueOf मुक्केबाजी कार्रवाई करने को देखा - तो आप भाषा की मदद के बिना एक ही प्रभाव प्राप्त कर सकते हैं:

Integer x = Integer.valueOf(100); 
Integer y = Integer.valueOf(100); 
System.out.println(x == y); // true 

से section 5.1.7 of the JLS:

यदि मूल्य पी बॉक्सिंग किया गया है तो सत्य, झूठी, बाइट, या श्रेणी में एक char \ u0000f, या 128 और 127 (समावेशी) के बीच एक int या छोटी संख्या है, तो r1 और r2 होने दें पी के किसी भी दो मुक्केबाजी रूपांतरण के परिणाम। यह हमेशा मामला है कि आर 1 == आर 2।

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

यह सुनिश्चित करता है कि अधिकांश सामान्य मामलों में, व्यवहार एक वांछित प्रदर्शन जुर्माना लगाए बिना वांछित होगा, विशेष रूप से छोटे उपकरणों पर। कम मेमोरी-सीमित कार्यान्वयन, उदाहरण के लिए, सभी चार और छोटे मानों को कैश कर सकते हैं, साथ ही साथ -32K से + 32K की सीमा में int और लंबे मान भी हो सकते हैं।

14

जावा -128 से 127

की तरह नीचे

Integer i1 = 127; 

परिणाम में

Integer i1 = Integer.valueOf(127); 

तो क्या वास्तव में पहले मामले के लिए हो रहा

Integer i1 = 127;<---Integer.valueOf(127); 
Integer i2 = 127;<---Integer.valueOf(127);<---Same reference as first 
है पूर्णांक की घोषणा करने के लिए पूर्णांक पूल का कहना है

वर्ग valueOf विधि

public static Integer valueOf(int i) { 
    if(i >= -128 && i <= IntegerCache.high) 
     return IntegerCache.cache[i + 128]; 
    else 
     return new Integer(i); 
} 

के लिए Integer के स्रोत कोड से तो आप एक ही संदर्भ प्राप्त करता है, तो मूल्य 127 को -128 के बीच है और आप फोन valueOf किसी और यह सिर्फ new Integer(i)

रिटर्न और क्योंकि संदर्भ में ही है आपके == ऑपरेटर इस श्रेणी के बीच valueOf द्वारा लौटा पूर्णांक के लिए काम करता है।

+2

+1। अन्य उत्तरों को लगता है कि यह सिर्फ जादू है। – EJP

7

जावा -128 to 127 श्रेणी में पूर्णांक वस्तुओं को कैश करता है। इसलिए, जब आप इस श्रेणी में wrapper ऑब्जेक्ट को मान निर्दिष्ट करने का प्रयास करते हैं, तो boxing ऑपरेशन Integer.valueOf विधि का आह्वान करेगा और बदले में यह पूल में पहले से मौजूद ऑब्जेक्ट का संदर्भ निर्दिष्ट करेगा।

दूसरी तरफ, यदि आप wrapper संदर्भ प्रकार पर इस श्रेणी के बाहर कोई मान निर्दिष्ट करते हैं, तो Integer.valueOf उस मान के लिए एक नया Integer ऑब्जेक्ट तैयार करेगा। और इसलिए इस सीमा के बाहर referenceInteger के लिए वस्तुओं होने मूल्य की तुलना आप false

तो,

Integer i = 127; --> // Equivalent to `Integer.valueOf(127)` 
Integer i2 = 127; 

// Equivalent to `Integer.valueOf(128)` 
// returns `new Integer(128)` for value outside the `Range - [-128, 127]` 
Integer i3 = 128; 
Integer i4 = 128; 

System.out.println(i == i2); // true, reference pointing to same literal 
System.out.println(i3 == i4); // false, reference pointing to different objects 

, जब आप new ऑपरेटर का उपयोग कर अपने पूर्णांक उदाहरण बना दे लेकिन, एक नई वस्तु पर बनाया जाएगा ढेर। तो,

Integer i = new Integer(127); 
Integer i2 = new Integer(127); 

System.out.println(i == i2); // false 
+0

आपकी i3 से i4 तुलना गलत है, क्योंकि आप 'इंटीजर' की बजाय 'int' का उपयोग कर रहे हैं। –

+0

@ जोन्स स्केट। ओह! माफ़ कीजिये। मुझे चारों स्थानों पर 'इंटीगर' होना चाहिए था। इसे संपादित करेंगे। पॉइंटिंग के लिए धन्यवाद :) –

+0

उत्तर मूल रूप से गलत है। जावा 'पूर्णांक अक्षर कैश नहीं' करता है। जावा * एंटीजर ऑब्जेक्ट्स * -128 से 127 * तक कैश करता है यदि आप उन्हें प्राप्त करने के लिए Integer.valueOf() कहते हैं, * जो ऑटो मुक्केबाजी में होता है, लेकिन ओपी के कोड में नहीं, यही कारण है कि यह उत्तर अपेक्षित नहीं देता है । – EJP