2012-04-14 9 views
42

मैं कैथी सिएरा और बर्ट बेट्स द्वारा एससीजेपी जावा 6 पढ़ रहा हूं और यह पुस्तक मुझे इतना भ्रमित कर रही है। पृष्ठ 245 पर वे बताते हैं कि नीचे दिया गया कोड।रैपर ऑब्जेक्ट्स की तुलना करने के लिए जावा में == ऑपरेटर का उपयोग

Integer i1 = 1000; 
Integer i2 = 1000; 
if(i1 != i2) 
System.out.println("different objects"); 

//Prints output 
different objects 
अगले ही पेज वे पर

तो कोड

Integer i3 = 10; 
Integer i4 = 10; 
if(i3 == i4) 
System.out.println("same objects"); 

//Prints output 
same objects 

निम्नलिखित मैं बहुत उलझन में हूँ! जब मैं इसे अपने आप पर आज़माता हूं तो ऐसा लगता है कि आप उसी तरह की तुलना करने के लिए == का उपयोग नहीं कर सकते जैसे आप बराबर() विधि का उपयोग करेंगे। == हमेशा मुझे 'झूठा' देता है भले ही इंटीजर वैरिएबल एक ही मान पर सेट हो (यानी 10)। क्या मैं सही हूँ? उसी इंटीजर ऑब्जेक्ट (समान मानों के साथ) की तुलना करने के लिए == का उपयोग करना हमेशा 'झूठा'

+1

मुझे लगता है कि इस लिंक आप मदद कर सकते हैं: //stackoverflow.com/questions/1514910/when-comparing-two-integers-in-java-does-auto-unboxing-occur – Tarik

+1

http://stackoverflow.com/questions/5277881/why-arent-integers- की डुप्लीकेट कैश्ड-इन-जावा – Patrick

+1

और यह: http://stackoverflow.com/questions/5117132/int ईगर-रैपर-ऑब्जेक्ट्स-शेयर-द-ए-इंस्टेंस-केवल-इन-द-वैल्यू-127, http://stackoverflow.com/questions/8427416/why-is-true-for-some-integer-objects – Patrick

उत्तर

51

उत्तर की कुंजी को ऑब्जेक्ट इंटर्निंग कहा जाता है। जावा इंटर्न छोटे नंबर (128 से कम), इसलिए Integer(n) के सभी उदाहरण इंटरनेशनल रेंज में n के साथ समान हैं। 128 से अधिक या उसके बराबर संख्याएं इंटर्न नहीं हैं, इसलिए Integer(1000) ऑब्जेक्ट्स एक-दूसरे के बराबर नहीं हैं।

+1

वाह! मैंने बस उसे भी देखा। क्यूं कर?? यह इतना भ्रमित है। इसके पीछे तर्क क्या है? – dido

+8

ध्यान दें कि केवल शाब्दिक, autoboxing और 'Integer.valueOf()' से प्राप्त ऑब्जेक्ट इंजेक्शन ऑब्जेक्ट्स हैं, जबकि 'नए इंटीजर' के साथ बनाए गए हमेशा अलग ऑब्जेक्ट्स –

+0

मुझे याद है कि छोटे स्ट्रिंग्स के लिए भी जाना जाता है, लेकिन मुझे यकीन नहीं है चाहे यह सच है और यदि हां, तो एक छोटे स्ट्रिंग को क्या माना जाता है। अपको इस बारे में कुछ पता है? –

7

आंतरिक के बारे में उपरोक्त उत्तर सही है। कुछ विचार करने के लिए हालांकि यदि आप करते हैं:

Integer i3 = new Integer(10); 
Integer i4 = new Integer(10); 

आपके पास नई वस्तुएं नहीं हैं क्योंकि आपने नई वस्तुओं को स्पष्ट रूप से बनाया है। यदि आप निम्नानुसार कोड लिखते हैं तो इसे इंटर्न किया जाएगा:

Integer i3 = Integer.valueOf(10); 
Integer i4 = Integer.valueOf(10); 

वे अब एक ही ऑब्जेक्ट फिर से होंगे। यदि आप src.zip फ़ाइल में Integer.java क्लास के अंदर valueOf विधि को देखते हैं तो आप देख सकते हैं कि यह कहां जांचता है कि int का मान -128 से 127 के बाहर है या नहीं, यह अन्य इंटीजर क्लास को अन्यथा कॉल करता है यह इसे कैश से लोड करता है।

14

आप Integer के लिए स्रोत कोड को देखो, तो आप Integer.valueOf(int)पूल सभी मान -128 127 कारण यह है कि छोटे पूर्णांक मान अक्सर इस्तेमाल किया है और इस तरह जमा/कैश नहीं होती के योग्य हैं कर रहे हैं देखेंगे।

Integer.java से सीधे लिया गया:

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

ध्यान दें कि यह पूलिंग कार्यान्वयन विशिष्ट है और जमा रेंज की कोई गारंटी नहीं है।

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

+1

दरअसल, सीमा में 'int' मानों के लिए' इंटेगर 'ऑब्जेक्ट्स का कैशिंग [-128, 127] [API दस्तावेज़] में निर्दिष्ट है (http://docs.oracle.com/javase/7/docs/api /java/lang/Integer.html#valueOf%28int%29), इसलिए सीमा का हिस्सा वास्तव में गारंटीकृत है। –

2
Integer i1 = 1000; 
Integer i2 = 1000; 

कंपाइलर 'बॉक्स' इंटीजर ऑब्जेक्ट के रूप में int 1000। ऐसा करने के लिए यह निम्न के स्रोत धर्मान्तरित:

Integer i1 = Integer.valueOf(1000); 
Integer i2 = Integer.valueOf(1000); 

अब valueOfnew Integer(1000) के लिए एक सरल कॉल हालांकि एक नया पूर्णांक वस्तु हर बार एक int दोनों समय और स्थान का खर्च आएगा बॉक्सिंग है बनाने हो सकता है। इससे बचने के लिए इंटीजर वर्ग int मानों की सीमित सीमा के लिए इंटीजर ऑब्जेक्ट्स की एक सरणी रखता है।

if(value> maxRange || value< minRange){ 
    //not in pool return new Integer 
    return new Integer(value); 
}else{ 
    //return pooled Integer object 
    //for the value, pool contains all Integer 
    //values from minRange to maxRange 
    return integerPool[value-minRange]; 
} 

गति स्मृति इस के लिए खो दिया बनाम प्राप्त की रेंज (यह afaik चूक -127 को 128 करने के लिए) कार्यक्रम शुरू में एक JVM तर्क के साथ की स्थापना द्वारा समायोजित किया जा सकता।

0

जब जावा == ऑपरेटर आदिम प्रकार के अलावा और कुछ तुलना करने के लिए प्रयोग किया जाता है, यह निर्देशात्मक समानता के लिए जाँच करता है; यह तब भी लागू होता है जब चीजों की तुलना की जा रही चीजें primitives लपेटा जाता है। इसके अलावा, valueOf विधि और कंपाइलर-जेनरेट किए गए ऑटोबॉक्सिंग कथन आम तौर पर एक नई वस्तु को वापस करने के लिए स्वतंत्र होते हैं जो किसी अन्य पूर्व-मौजूदा संदर्भ के संदर्भ में नहीं होगा, या किसी मौजूदा ऑब्जेक्ट का संदर्भ वापस करने के लिए (जो निश्चित रूप से होगा , एक ही वस्तु की पहचान करने वाले किसी भी पूर्व-मौजूदा संदर्भ के संदर्भ-संदर्भ के बराबर हो)। कार्यान्वयन एक मूल्यों के लिए Integer उदाहरणों में से "पूल" बनाए रखने के लिए आवश्यक हैं 127 तक -128, ऐसा है कि उस सीमा के भीतर किसी विशेष नंबर पर Integer.valueOf के लिए सभी कॉल एक ही वस्तु के लिए संदर्भ वापस आ जाएगी, पर इसके अलावा एक कार्यान्वयन के लिए स्वतंत्र होगा अन्य जैसे

static Integer [] intPool = new Integer[256]; 

public Integer valueOf(int n) 
{ 
    int hash = (n*0x18675309) >>> 24; 
    Integer instance = intPool[n]; 
    if (instance == null && instance.value != n) 
    { 
    instance = new Integer(n); 
    intPool[hash] = instance ; 
    } 
    return instance; 
} 

कुछ मैं विशेष रूप से जावा कार्यान्वयन, ऐसा कुछ करने के लिए के बाद से कई मामलों में "कैश हिट" अनुपात 0% के पास हो सकता है और अतिरिक्त समय कैश में उदाहरणों की तलाश में खर्च की उम्मीद नहीं है कर बर्बाद हो जाएगा। फिर भी, वहाँ किसी भी गारंटी नहीं है कि एक संदर्भ instanceOf द्वारा वापस कुछ पिछले संदर्भ कि विधि द्वारा लौटाए से मेल नहीं खाएगी कभी नहीं है (भले ही पिछले संदर्भ कि विधि द्वारा लौटाए से मेल नहीं खाता, कुछ कैशिंग एल्गोरिदम संभवतः यह करने के लिए कारण हो सकता है एक पहले संदर्भ लौटने पर ताला लगा। लॉकिंग की कमी कोड और कुछ वापस जाने के लिए सही मान के साथ एक पूर्णांक के लिए एक संदर्भ से कारण कभी नहीं होगा बिना खासकर अगर पूल से अधिक थ्रेड द्वारा साझा किया जाता है, लेकिन जो में अप्रत्याशित बदलाव के कारण हो सकता है वापस संदर्भ बराबर तुलना करें)। कन्स्ट्रक्टर new Integer(n) का उपयोग करके सीधे बनाए गए Integer ऑब्जेक्ट्स का संदर्भ केवल अद्वितीय होने की गारंटी है; कोड जो valueOf द्वारा दिए गए किसी भी संदर्भ से मेल खाने के लिए valueOf द्वारा लौटाए गए किसी भी संदर्भ की अपेक्षा करता है, वास्तव में यह नहीं देखा गया कि यह मेल नहीं खाता है, इसे तोड़ दिया जाना चाहिए।

0

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

0

"==" हमेशा स्मृति स्थान की तुलना या मूल्यों के संदर्भ आपत्ति है। बराबर विधि हमेशा मानों की तुलना करती है। लेकिन बराबर भी मूल्यों की तुलना करने के लिए अप्रत्यक्ष रूप से "==" ऑपरेटर का उपयोग करता है। इंटेगर -128 से + 127 तक मानों को संग्रहीत करने के लिए इंटीजर कैश का उपयोग करता है। अगर == ऑपरेटर का उपयोग -128 से 127 के बीच किसी भी मान की जांच करने के लिए किया जाता है तो यह सच हो जाता है। अगर के रूप में

Integer i1 = -128; 
Integer i2 = -128; 
System.out.println(i1 == i2); // returns true 

ऊपर रेंज के अलावा अन्य 127 के लिए -128 के बीच किसी भी मूल्य तो यह गलत

Integer i1 = 1000; 
Integer i2 = 1000; 
System.out.println(i1 == i2); // returns false 

Refer the link रिटर्न कुछ अतिरिक्त जानकारी के लिए

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