जावा: इंटेगर बराबर ==


152

जावा 1.5 के रूप में, आप काफी इंटरचेंज कर सकते हैं Integerके साथ intकई स्थितियों में।

हालांकि, मुझे अपने कोड में एक संभावित खराबी मिली जिसने मुझे थोड़ा आश्चर्यचकित किया।

निम्नलिखित कोड:

Integer cdiCt = ...;
Integer cdsCt = ...;
...
if (cdiCt != null && cdsCt != null && cdiCt != cdsCt)
    mismatch = true;

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

सशर्त को बदलना:

if (cdiCt != null && cdsCt != null && !cdiCt.equals(cdsCt))

समस्या को ठीक किया।

क्या कोई इस बारे में कुछ प्रकाश डाल सकता है कि ऐसा क्यों हुआ? अब तक, मैंने केवल अपने पीसी पर अपने लोकलहोस्ट के व्यवहार को देखा है। इस विशेष मामले में, कोड ने इसे सफलतापूर्वक लगभग 20 तुलनाओं के साथ बनाया, लेकिन 2 पर विफल रहा। समस्या लगातार प्रतिलिपि प्रस्तुत करने योग्य थी।

यदि यह एक प्रचलित समस्या है, तो यह हमारे अन्य वातावरणों (देव और परीक्षण) पर त्रुटियों का कारण होना चाहिए, लेकिन अभी तक, इस कोड को स्निपेट निष्पादित करने वाले सैकड़ों परीक्षणों के बाद किसी ने भी समस्या की सूचना नहीं दी है।

क्या यह अभी भी ==दो Integerमूल्यों की तुलना करने के लिए उपयोग करने के लिए वैध नहीं है ?

नीचे दिए गए सभी ठीक उत्तरों के अलावा, निम्नलिखित स्टैकओवरफ़्लो लिंक में बहुत अधिक अतिरिक्त जानकारी है। यह वास्तव में मेरे मूल प्रश्न का उत्तर दे सकता था, लेकिन क्योंकि मैंने अपने प्रश्न में ऑटोबॉक्सिंग का उल्लेख नहीं किया था, यह चयनित सुझावों में नहीं दिखा था:

कंपाइलर / जेवीएम सिर्फ ऑटोबॉक्सिंग को "सिर्फ काम" क्यों नहीं बना सकते?

जवाबों:


238

जेवीएम इंटेगर के मूल्यों को कैच कर रहा है। == केवल -128 और 127 के बीच काम करता है http://www.owasp.org/index.php/Java_gotchas#Immutable_Objects_.2F_Wrapper_Class_Caching


1
धन्यवाद, यह निश्चित रूप से बताता है कि क्यों 137 विफल रहता है! और यह मेरे सवाल का भी जवाब देता है कि यह एक प्रचलित समस्या क्यों नहीं है, 95% मामलों में मैं मुठभेड़ करने जा रहा हूं, मूल्य 127 से कम होगा। अब इसे पकड़ने के लिए अच्छा है हालांकि 5% के लिए जहां यह नहीं है।
जेरेमी गुडेल

1
दिलचस्प पक्ष ध्यान दें: कुछ हफ़्ते पहले तक, cdiCt और cdsCt दोनों ही इन्टल्स थे, इसलिए यह ठीक था, लेकिन मुझे उन्हें अलग स्थिति को संभालने के लिए इंटेगर बनाना पड़ा, जिसे अलग-अलग तरीके से हैंडल किया गया ...
जेरिस गुडेल

3
@ जेरेमी हाँ, यह एक बहुत ही अस्पष्ट समस्या है, लेकिन एक सामान्य नियम के रूप में आप। (ऑब्जेक्ट्स के लिए) और आदिमों के लिए == का उपयोग करते हैं। आप समानता परीक्षण के लिए ऑटोनबॉक्सिंग पर भरोसा नहीं कर सकते।
एडम

1
Lol, आप के लिए फिर से निशान की जाँच करें! लगता है कि कॉलिन के पास पहले से ही वैसे भी पर्याप्त से अधिक अंक हैं।
जेरेमी गुडेल

2
ध्यान दें कि नया Integer (1)! = New Integer (1) भी। नया ALWAYS एक नया पता देता है। ऑटोबॉक्सिंग एक कैश्ड संस्करण का उपयोग करता है। अन्य तरीके जो इंटेर्ज को लौटाते हैं (उन्हें नया किए बिना) शायद कैश किए गए मूल्य को भी वापस कर दें।
बिल के

77

आप Integerएक साधारण के साथ दो की तुलना नहीं कर सकते ==हैं ताकि वे वस्तुएं हों इसलिए अधिकांश समय संदर्भ एक समान नहीं होंगे।

एक चाल है, Integer-128 और 127 के बीच, संदर्भ वही होगा Integer.valueOf()जो ऑटोबॉक्सिंग उपयोग करता है जो छोटे पूर्णांक को कैश करता है ।

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


संसाधन:

उसी विषय पर:


1
जेएलएस से गारंटी है या सिर्फ ओरेकल जेवीएम के लिए?
थोर्बोजर्न रेव एंडरसन

उद्धृत भाग JLS से है, इसलिए यह JLS से एक गारंटी है
कॉलिन हेबर्ट

पुन: गारंटी। मैं अभी भी इस पर बहुत ज्यादा भरोसा नहीं करता। new Integer(1) == new Integer(1)अभी भी झूठा है।
थिलो

@ थिलो new ... == new ...हमेशा है false
एमसी सम्राट

2
@ थिलो ट्रू, हमेशा equals()वस्तुओं के साथ व्यवहार करते समय उपयोग करें । जावा को सीखते समय यह पहली चीजों में से एक होना चाहिए। वैसे, मैंने अनुमान लगाया होगा कि कंस्ट्रक्टर Integerनिजी था, यानी कि उदाहरण हमेशा valueOf()विधि के माध्यम से बनाए गए थे । लेकिन मैं देखता हूं कि कंस्ट्रक्टर सार्वजनिक है।
एम सी सम्राट

5

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


अच्छा जवाब है, लेकिन यह स्पष्ट नहीं है कि यह केवल 137 के लिए असफल क्यों है।
जेरेमी गुडेल

4

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

क्या मैं यह जोड़ सकता हूं कि यदि आप जो कर रहे हैं, वह क्यों ifकरना है?

mismatch = ( cdiCt != null && cdsCt != null && !cdiCt.equals( cdsCt ) );

4

"==" हमेशा स्मृति स्थान या मान संदर्भों की तुलना करें। बराबरी का तरीका हमेशा मूल्यों की तुलना करता है। लेकिन मूल्यों की तुलना करने के लिए "==" ऑपरेटर का भी समान रूप से अप्रत्यक्ष रूप से उपयोग होता है।

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

कुछ अतिरिक्त जानकारी के लिए लिंक देखें


1

साथ ही उपयोग करने की शुद्धता के लिए ==आप तुलना Integerकरने से पहले किसी एक मान को अनबॉक्स कर सकते हैं ==, जैसे:

if ( firstInteger.intValue() == secondInteger ) {..

दूसरा ऑटो अनबॉक्स होगा (निश्चित रूप से आपको nullपहले जांचना होगा )।


0

इन महान जवाबों के अलावा, मैंने जो सीखा है, वह है:

जब तक आप वस्तुओं की तुलना == से नहीं करते, जब तक आप उनके संदर्भों से उनकी तुलना करने का इरादा नहीं करते।

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