2009-07-18 19 views
8

इस कोड पर विचार करें:जावा का == पर असंगत व्यवहार

class test { 
    public static void main(String[] args) { 
     test inst_test = new test(); 
     int i1 = 2000; 
     int i2 = 2000; 
     int i3 = 2; 
     int i4 = 2; 
     Integer Ithree = new Integer(2); // 1 
     Integer Ifour = new Integer(2); // 2 
     System.out.println(Ithree == Ifour); 
     inst_test.method(i3 , i4); 
     inst_test.method(i1 , i2); 
    } 
    public void method(Integer i , Integer eye) { 
     System.out.println(i == eye); 
    } 
} 

यह प्रिंट:

false 
true 
false 

मैं समझता हूँ कि पहले false, == ऑपरेटर केवल चेक के दो संदर्भों अगर एक ही काम कर रहे हैं वस्तु, जो इस मामले में नहीं हैं।

निम्नलिखित true और false मुझे मेरे सिर खरोंच है। जावा i3 और i4 बराबर क्यों मानेंगे लेकिन i1 और i2 अलग-अलग होंगे? दोनों को इंटीजर में लपेटा गया है, दोनों को झूठा मूल्यांकन नहीं करना चाहिए? क्या इस असंगतता के लिए कोई व्यावहारिक कारण है?

+2

मेरा मानना ​​है कि FindBugs अपने त्रुटि की आपको बता जाएगा। –

उत्तर

15

autoboxing (के रूप में method करने के लिए अपने कॉल में इस्तेमाल छोटे मूल्यों की एक कैश का उपयोग करता Java Language Specification section 5.1.7 से:।

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

इसके तुरंत बाद spec का चर्चा हिस्सा भी दिलचस्प है। विशेष रूप से एक JVM अधिक मूल्यों को कैश कर सकते हैं अगर यह करना चाहता है - तुम क्या कर के परिणामों के बारे में सुनिश्चित नहीं किया जा सकता:

Integer i1 = 129; 
Integer i2 = 129; 
boolean b = (i1 == i2); 
+0

यह कुछ गंभीर रूप से दुष्ट तर्क है - मुझे लगता है कि यह प्रदर्शन कारणों से किया गया है? –

+0

क्या इसका वास्तव में लाभ है? मुझे लगता है कि यह एक अपमानजनक डिजाइन निर्णय है। – andandandand

+0

6u14 (और विभिन्न पिछले पी-वेरिएंट) में आंतरिक श्रेणी बढ़ाने के लिए एक विकल्प है। कुछ मानक और प्रोग्रामिंग शैलियों के लिए यह महत्वपूर्ण है। –

2

ऐसा इसलिए है क्योंकि मुक्केबाजी एक निश्चित मूल्य के नीचे पूर्णांक बनाता है (128, मुझे लगता है) कुछ पूर्वनिर्धारित वस्तु का संदर्भ देता है, और नई वस्तुओं के लिए उच्च मान।

7

ऑटोबॉक्सिंग करते समय, -128 और 127 के बीच इंटीग्रेट कैश किए जाते हैं, और उसी रैपर ऑब्जेक्ट को वापस कर दिया जाता है। \ U0000 और \ u007F

के बीच बूलियन मानों और चार मानों के साथ वही है जो आपको अधिकतर समय मिलता है, हालांकि यह JVM कार्यान्वयन पर निर्भर करता है।

+3

मुझे लगता था कि यह जेवीएम-निर्भर भी था, लेकिन यह वास्तव में कल्पना में है। –

+2

(या बल्कि, यह दूसरों के लिए उन मूल्यों के लिए निर्दिष्ट किया है, लेकिन नहीं।) –

0

मुझे लगता है कि रैपिंग इंटीजर ऑब्जेक्ट्स की संख्या को कम करने की कोशिश करता है और केवल एक ऑब्जेक्ट बनाता है जो 2 स्मृति को भी बचाता है।

ऑब्जेक्ट्स पर == का कभी भी उपयोग न करना याद रखें जो आप कभी नहीं जानते कि क्या होता है। वस्तुओं में पुरातन का

+0

हाँ, के रूप में कई ने कहा है, का उपयोग नहीं करते == जब तक विशेष प्रभाव की मांग कर रहे हैं कि द्वारा समर्थन कर रहे हैं "जानता है कि क्या होता है" और सामान्य उपयोग में: बूलियन बूओन = Boolean.valueOf (i.intValue() == eye.intValue()); System.out.println (booLean.toString()); –

0

पूर्णांक वर्ग कुछ अक्सर इस्तेमाल उदाहरणों में से एक कैश होते हैं। ,

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

इस स्ट्रिंग होना शामिल की तरह है (सूरज JDK 1.6 से कोड): मानों की श्रेणी आम तौर पर JVM करने के लिए JVM से भिन्न होता है (कभी कभी भी विन्यास है), लेकिन सामान्य रूप में प्रासंगिक कोड की तरह कुछ है चूंकि यह दोनों स्मृति को बचाता है और संदर्भ का उपयोग करके परीक्षण समानता की अनुमति देता है (उदाहरण के लिएके स्थान पर == के बराबर होती है)

1

autoboxing Integer.valueOf (i), नहीं नई पूर्णांक (i) का उपयोग करता है वर्ग पूर्णांक की एक वस्तु के निर्माण के लिए।

के रूप में अन्य लोगों ने कहा, valueOf() ज्यादातर अंतरिक्ष दक्षता के लिए, एक कैश का उपयोग करता।

संदर्भ प्रकार पर == का उपयोग न करें, यह लगभग हमेशा एक गलती है।

0

autoboxing कुछ कैशिंग तंत्र का उपयोग करें। आम तौर पर आपको कभी भी == पर भरोसा नहीं करना चाहिए, समानता की जांच के लिए हमेशा equals का उपयोग करें।

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