जावा में इंटेगर रैपर की तुलना करते समय 128 == 128 झूठा लेकिन 127 == 127 सच क्यों है?


172
class D {
    public static void main(String args[]) {
        Integer b2=128;
        Integer b3=128;
        System.out.println(b2==b3);
    }
}

आउटपुट:

false

class D {
    public static void main(String args[]) {
        Integer b2=127;
        Integer b3=127;
        System.out.println(b2==b3);
    }
}

आउटपुट:

true

नोट: -128 और 127 के बीच की संख्या सही है।


10
आपको bexhuff.com/2006/11/java-1-5-autoboxing-wackyness जानकारीपूर्ण मिल सकती है।
डोमिनिक रॉगर

1
आप इस सवाल को पूछने के लिए कैसे पहुंचे? यह वास्तव में मजेदार है, लेकिन किसी को कभी भी "वास्तविक दुनिया में" जैसी कोई चीज़ नहीं मिलती है ... या?
घोड़ी इनफिनिटस

जवाबों:


217

जब आप जावा में एक संख्या शाब्दिक संकलित करते हैं और इसे एक पूर्णांक (राजधानी I) में संकलित करते हैं, तो संकलक निकलता है:

Integer b2 =Integer.valueOf(127)

जब आप ऑटोबॉक्सिंग का उपयोग करते हैं तो कोड की यह लाइन भी उत्पन्न होती है।

valueOf इस तरह लागू किया जाता है कि कुछ निश्चित संख्याएं "जमा" होती हैं, और यह 128 से छोटे मूल्यों के लिए एक ही उदाहरण देता है।

जावा 1.6 स्रोत कोड से, लाइन 621:

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

का मान highसकते हैं एक और मूल्य के लिए कॉन्फ़िगर किया, प्रणाली संपत्ति के साथ।

-Djava.lang.Integer.IntegerCache.high = 999

यदि आप उस सिस्टम प्रॉपर्टी के साथ अपना प्रोग्राम चलाते हैं, तो यह सच हो जाएगा!

स्पष्ट निष्कर्ष: कभी भी एक जैसे होने के दो संदर्भों पर भरोसा न करें, हमेशा उनकी तुलना .equals()विधि से करें।

तो b2.equals(b3)b2, b3 के सभी तार्किक समान मूल्यों के लिए सच प्रिंट होगा।

ध्यान दें कि Integerकैश प्रदर्शन के कारणों के लिए नहीं है, बल्कि जेएलएस, खंड 5.1.7 के अनुरूप है ; ऑब्जेक्ट की पहचान -128-127 से लेकर इंक्लूसिव के लिए दी जानी चाहिए।

पूर्णांक # valueOf (int) भी इस व्यवहार का दस्तावेजीकरण करता है:

इस पद्धति से अक्सर अनुरोधित मूल्यों को कैशिंग द्वारा बेहतर स्थान और समय प्रदर्शन प्राप्त करने की संभावना है। यह विधि हमेशा -128-127 से लेकर 127 तक के मूल्यों को कैश कर सकती है, इस रेंज के बाहर अन्य मूल्यों को कैश कर सकती है।


1
ध्यान दें कि 127 से छोटे मूल्यों को जावा द्वारा अनदेखा किया जाएगा और Integer.MAX_VALUE-128 की तुलना में बड़े मानों को कैप किया जाएगा।
एंड्रियास पीटरसन

पूर्णांक जावा 5 और उच्चतर में बाइट मानों के लिए कैश किए जाते हैं, जिससे नया इंटेगर (1) == नया इंटेगर (1) बन जाता है। हालांकि, यह जावा 1.4 या उससे कम के मामले में नहीं है, इसलिए यदि आपको अंततः उस वातावरण को डाउनग्रेड करना है तो सावधान रहें।
MetroidFan2002

11
नहीं, यह गलत है। new Integer (1) == नया Integer (1) jvm की परवाह किए बिना झूठा है। AFAIK संकलक "नए" कीवर्ड पर धोखा नहीं देगा। यह हमेशा एक नई वस्तु तुरंत चाहिए।
एंड्रियास पीटरसन

1
@ होलगर दिलचस्प बिंदु। तो यह दुष्प्रभाव का अनुकूलन करने के लिए दूर की अनुमति नहीं है हो सकता है - लेकिन यह एक कस्टम impl साथ JDK से पूर्णांक वर्ग को बदलने के लिए ... (मत पूछो क्यों किसी को है कि पागल हो जाएगा) तकनीकी रूप से संभव है
एंड्रियास पीटरसन

1
@AndreasPetersson सुनिश्चित करें। "कंपाइलर" का अर्थ है जेआईटी कंपाइलर, जो वास्तविक कार्यान्वयन वर्ग को ठीक से जानता है और केवल ऑप्टिमाइज़ कर सकता है, यदि कंस्ट्रक्टर का कोई दुष्प्रभाव नहीं है। या केवल साइड इफेक्ट्स को पुन: पेश करने के लिए अभिव्यक्ति का अनुकूलन करें, इसके बाद उपयोग करें false। दरअसल, यह आज पहले से ही हो सकता है, एस्केप एनालिसिस और स्केलर रिप्लेसमेंट को लागू करने के साइड इफेक्ट के रूप में।
होल्गर

24

ऑटोबॉक्सिंग कैश -128 से 127। यह जेएलएस ( 5.1.7 ) में निर्दिष्ट है ।

यदि मूल्य p बॉक्सिंग किया जा रहा है तो सही, गलत, एक बाइट, रेंज में एक चार्ट \ u0000 से \ u007f, या -128 और 127 के बीच एक इंट या शॉर्ट नंबर है, तो r1 और r2 को किन्हीं भी दो रूपांतरणों के परिणाम दें पी के। यह हमेशा ऐसा होता है कि r1 == r2।

वस्तुओं के साथ काम करते समय याद रखने का एक सरल नियम है - .equalsयदि आप जांचना चाहते हैं कि क्या दो वस्तुएं "बराबर" हैं, तो उपयोग करें ==जब आप यह देखना चाहते हैं कि क्या वे एक ही उदाहरण की ओर इशारा करते हैं।


1
नोट: JLS जावा 9 में बदल गया। यह अब केवल संकलन समय स्थिर अभिव्यक्तियों के लिए गारंटी है ; स्वीकृत उत्तर के लिए अद्यतन देखें।
स्टीफन सी।

9

आदिम डेटा प्रकारों का उपयोग, ints, दोनों मामलों में सही उत्पादन करेगा, अपेक्षित आउटपुट।

हालाँकि, जब से आप पूर्णांक वस्तुओं का उपयोग कर रहे हैं == ऑपरेटर का एक अलग अर्थ है।

वस्तुओं के संदर्भ में, == यह देखने के लिए जाँच करता है कि क्या चर समान वस्तु संदर्भ को संदर्भित करते हैं।

वस्तुओं के मूल्य की तुलना करने के लिए आपको बराबर () विधि का उपयोग करना चाहिए

 b2.equals(b1)

जो इंगित करेगा कि क्या b2 b1 से कम है, से अधिक है, या इसके बराबर है (विवरण के लिए API की जाँच करें)


7

यह जावा से संबंधित मेमोरी मेमोरी है।

स्मृति को बचाने के लिए, जावा उन सभी आवरण वस्तुओं को फिर से उपयोग करता है जिनके मूल्य निम्न श्रेणी में आते हैं:

सभी बूलियन मान (सच्चे और झूठे)

सभी बाइट मान

\ U0000 से \ u007f (यानी 0 से 127 तक दशमलव में सभी वर्ण मान)

-128 से 127 तक सभी लघु और पूर्णांक मान।


3

Integer.java पर एक नज़र डालें, अगर मूल्य -128 और 127 के बीच है, यह कैश्ड पूल, इसलिए का उपयोग करेगा (Integer) 1 == (Integer) 1, जबकि(Integer) 222 != (Integer) 222

 /**
 * Returns an {@code Integer} instance representing the specified
 * {@code int} value.  If a new {@code Integer} instance is not
 * required, this method should generally be used in preference to
 * the constructor {@link #Integer(int)}, as this method is likely
 * to yield significantly better space and time performance by
 * caching frequently requested values.
 *
 * This method will always cache values in the range -128 to 127,
 * inclusive, and may cache other values outside of this range.
 *
 * @param  i an {@code int} value.
 * @return an {@code Integer} instance representing {@code i}.
 * @since  1.5
 */
public static Integer valueOf(int i) {
    assert IntegerCache.high >= 127;
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}       

0

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

समानता के लिए पूर्णांक वस्तुओं की तुलना करने के लिए, equalsविधि का उपयोग करें ।

, पहचान ऑपरेटर का उपयोग करके समानता के लिए पूर्णांक वस्तुओं की तुलना की कोशिश न करें ==

ऐसा हो सकता है कि कुछ समान मूल्य समान वस्तुएं हों, लेकिन यह ऐसी चीज नहीं है जिस पर आमतौर पर भरोसा किया जाना चाहिए।


-4

मैंने निम्नलिखित लिखा क्योंकि यह समस्या पूर्णांक के लिए विशिष्ट नहीं है। मेरा निष्कर्ष यह है कि यदि आप एपीआई का गलत तरीके से उपयोग करते हैं, तो आप अक्सर गलत व्यवहार देखते हैं। इसका सही ढंग से उपयोग करें और आपको सही व्यवहार देखना चाहिए:

public static void main (String[] args) {
    Byte b1=127;
    Byte b2=127;

    Short s1=127; //incorrect should use Byte
    Short s2=127; //incorrect should use Byte
    Short s3=128;
    Short s4=128;

    Integer i1=127; //incorrect should use Byte
    Integer i2=127; //incorrect should use Byte
    Integer i3=128;
    Integer i4=128;

    Integer i5=32767; //incorrect should use Short
    Integer i6=32767; //incorrect should use Short

    Long l1=127L;           //incorrect should use Byte
    Long l2=127L;           //incorrect should use Byte
    Long l3=13267L;         //incorrect should use Short
    Long l4=32767L;         //incorrect should use Short
    Long l5=2147483647L;    //incorrect should use Integer 
    Long l6=2147483647L;    //incorrect should use Integer
    Long l7=2147483648L;
    Long l8=2147483648L;

    System.out.print(b1==b2); //true  (incorrect) Used API correctly
    System.out.print(s1==s2); //true  (incorrect) Used API incorrectly
    System.out.print(i1==i2); //true  (incorrect) Used API incorrectly
    System.out.print(l1==l2); //true  (incorrect) Used API incorrectly

    System.out.print(s3==s4); //false (correct) Used API correctly
    System.out.print(i3==i4); //false (correct) Used API correctly
    System.out.print(i5==i6); //false (correct) Used API correctly
    System.out.print(l3==l4); //false (correct) Used API correctly
    System.out.print(l7==l8); //false (correct) Used API correctly
    System.out.print(l5==l6); //false (correct) Used API incorrectly

}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.