2012-06-10 28 views
5

प्रकार पूर्णांक है कि स्थिर कारखाने विधि valueOf फोन के दो संदर्भों पर विचार करें जिन्हें आप नीचे देख इसे का उपयोग जावा में अपरिवर्तनीय वस्तुओं की तुलना करना ठीक है == बराबर विधि का उपयोग करने के बजाय == का उपयोग करके ए और बी की तुलना करना ठीक है। मैं अनुमान लगा रहा हूं कि valueOf विधि यह सुनिश्चित करती है कि मान 10 के साथ इंटीजर का केवल एक उदाहरण बनाया गया है और इस उदाहरण का संदर्भ मूल्य 10 के साथ बनाए गए प्रत्येक इंटीजर के लिए वापस किया जाता है।बजाय बराबर होती है

सामान्यतः, तुलना करना ठीक है एक अपरिवर्तनीय वर्ग के दो संदर्भ जो समान स्थिर फैक्ट्री विधि में कॉल का उपयोग करके समान रूप से == का उपयोग करके बनाए जाते हैं?

संपादित करें: इंटीजर वर्ग का उपयोग उदाहरण के रूप में किया गया था। मुझे पता है कि 127 तक की इंटर्स सच हो जाएंगी यदि उनकी तुलना == का उपयोग करके की जाती है। मुझे यह जानने की ज़रूरत है कि जब मैं अपनी खुद की अपरिवर्तनीय कक्षा बनाउंगा, तो एक विधि बनाने के साथ MyImmutable कहें() जो सुनिश्चित करेगा कि कोई डुप्लिकेट MyImutable ऑब्जेक्ट्स नहीं बनाए जाते हैं, तो यह ठीक होगा अगर मैं 2 विधि बनाने के द्वारा बनाए गए MyImutable संदर्भों की तुलना करता हूं बराबर के बजाय == का उपयोग कर।

+0

कृपया पढ़ें [यह] (http: //www.javabeat।नेट/क्यूना/13-बीच-अंतर-अंतर-बराबर-और-/0) –

+2

अपरिवर्तनीयता का तात्पर्य है कि वे बदल नहीं सकते हैं। यह सुनिश्चित करने के लिए कि समान मान पैरामीटर के लिए समान मान वापस आते हैं, कैशिंग (कोई 'नया') के साथ विशेष देखभाल की आवश्यकता है। –

+0

आप उन प्रकारों के बराबर के बराबर '==' का उपयोग कर सकते हैं जहां बराबर ओवरराइड नहीं किया गया है। चूंकि यह भविष्य में बदल सकता है, बराबर लगभग हमेशा बेहतर होता है। एकमात्र बार मैं कहूंगा कि '==' बेहतर है 'एनम' जैसे प्रकारों के साथ जो 'शून्य' हो सकता है और '==' इस मामले में कोड को सरल बनाता है। –

उत्तर

6

नहीं, यह सामान्य रूप से सुरक्षित नहीं है। == ऑपरेटर संदर्भों की तुलना करता है, मूल्यों की नहीं।

== का उपयोग -128 और 127 के बीच पूर्णांक के लिए काम करता है, लेकिन अन्य पूर्णांक के लिए नहीं। निम्नलिखित कोड को दर्शाता है कि == हमेशा काम नहीं करेगा: ideone

इस व्यवहार के लिए स्पष्टीकरण Integer.valueOf के कार्यान्वयन में निहित है::

public static Integer valueOf(int i) { 
    final int offset = 128; 
    if (i >= -128 && i <= 127) { // must cache 
     return IntegerCache.cache[i + offset]; 
    } 
    return new Integer(i); 
} 

source

Integer a = Integer.valueOf(10); 
Integer b = Integer.valueOf(10); 
System.out.println(a == b); 

true 

Integer c = Integer.valueOf(1000); 
Integer d = Integer.valueOf(1000); 
System.out.println(c == d); 

false 

ऑनलाइन काम कर यह देखें

यह भी नहीं कि मानक के लिए मुक्केबाजी पूर्णांक की आवश्यकता है छोटे इनपुट (-128 से 127) समान संदर्भ वाले ऑब्जेक्ट्स देता है।

5.1.7 मुक्केबाजी रूपांतरण

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

हालांकि मानक इस सीमा के बाहर पूर्णांक के लिए ऐसी कोई गारंटी नहीं देता है।


सामान्य में, यह बराबर है के बजाय का उपयोग कर == द्वारा अपरिवर्तनीय वर्ग है कि एक ही स्थिर कारखाने विधि के लिए एक कॉल का उपयोग कर बनाई गई हैं के दो संदर्भों तुलना करने के लिए ठीक है?

जैसा ऊपर दिखाया गया है, यह सामान्य रूप से काम नहीं करेगा। लेकिन यदि आप सुनिश्चित करते हैं कि एक ही मूल्य के साथ दो अपरिवर्तनीय वस्तुओं का हमेशा एक ही संदर्भ होता है, तो हाँ, यह काम कर सकता है।हालांकि कुछ नियम हैं जो आपको सावधानीपूर्वक पालन करना चाहिए:

  • निर्माता को सार्वजनिक नहीं होना चाहिए।
  • स्थिर विधि के माध्यम से आप जो भी ऑब्जेक्ट बनाते हैं उसे कैश किया जाना चाहिए।
  • हर बार जब आप किसी ऑब्जेक्ट को बनाने के लिए कहा जाता है तो आपको पहले यह देखने के लिए कैश की जांच करनी होगी कि क्या आपने पहले से ही एक ही ऑब्जेक्ट को उसी मान के साथ बनाया है या नहीं।
+0

मेरा प्रश्न इंटीजर वर्ग के बारे में नहीं है। मैं एक सामान्य जवाब प्राप्त करने की उम्मीद कर रहा हूं। – CKing

+0

मुझे खेद है। मैं आखिरी हिस्सा चूक गया। मैं अपनी आकाशगंगा एस 3 के माध्यम से लॉग इन हूं और यह डेस्कटॉप/लैपटॉप के समान नहीं है। :) – CKing

+0

यह वास्तव में वह उत्तर है जिसे मैं ढूंढ रहा था। आपका बहुत बहुत धन्यवाद! – CKing

7

== और बराबर() मूल रूप से अलग है।

आप अधिक जानकारी के लिए इस पोस्ट को पढ़ना चाहिए:

Difference between Equals/equals and == operator?

यह अपरिवर्तनीय वस्तुओं के साथ कोई संबंध नहीं है।

+1

मुझे बराबर और == बहुत अच्छी तरह से अंतर पता है। स्पष्ट होने से पहले कृपया मेरे प्रश्न को समझने का प्रयास करें। – CKing

+1

ठीक है। मैं आपको एक उदाहरण दूंगा जहां तुलना करने के लिए == का उपयोग करना ठीक होगा। उदाहरण के लिए, मेरे पास एक ऐसा एप्लिकेशन है जिसमें उपयोगकर्ता ऑब्जेक्ट है। मैं सुनिश्चित करता हूं कि मैं केवल प्रत्येक उपयोगकर्ता यानी के लिए एक उदाहरण को तुरंत चालू करता हूं। जब मैं आईडी 123 के साथ उपयोगकर्ता के लिए कॉल करता हूं, तो आईडी 123 के साथ मेरे पूरे एप्लिकेशन में हमेशा एक ही उपयोगकर्ता ऑब्जेक्ट मौजूद होगा। इस मामले में, == का उपयोग करके 2 उपयोगकर्ता ऑब्जेक्ट्स की तुलना करने के लिए स्वीकार्य है यह देखने के लिए कि वे एक ही उपयोगकर्ता हैं या नहीं। –

+0

अन्यथा, आमतौर पर == का उपयोग करके 2 ऑब्जेक्ट्स की तुलना करना ठीक नहीं है, अगर मैंने स्पष्ट कहा है, लेकिन संपादन से पहले आपका प्रश्न पूरी तरह से एक अलग दिशा थी। –

1

वे एक ही वस्तु नहीं हैं, इसलिए == सत्य नहीं होगा। वस्तुओं के साथ, सुरक्षित रहें और equals() का उपयोग करें।

+2

तकनीकी रूप से, 'valueOf' कैश (डिफ़ॉल्ट रूप से) -128 से 127 इसलिए इस मामले में 'a == b' सत्य होगा। लेकिन हां, वैसे भी निश्चित रूप से '.equals' का उपयोग करें। – Kevin

+0

मैं एक कक्षा के बारे में बात कर रहा हूं जो सुनिश्चित करता है कि कोई डुप्लिकेट नहीं बनाया गया है। उत्तर देने के लिए कृपया एक प्रश्न समझने का प्रयास करें .. – CKing

+1

@bot: आपका मूल प्रश्न यह नहीं बताता कि कक्षा ने सुनिश्चित किया कि कोई डुप्लीकेट नहीं बनाया गया था। इस उत्तर को पोस्ट करने के बाद आपने अपना प्रश्न संपादित किया। –

5

यदि आपकी फैक्ट्री विधि बराबर इनपुट के लिए एक ही वस्तु लौटाती है, तो यह == के साथ उनकी तुलना करना सुरक्षित है। उदाहरण के लिए String.intern इस तरह से काम करता है। Enums की तुलना भी == के साथ की जा सकती है। लेकिन Integer.valueOf केवल उसी वस्तु को -128 के लिए देता है ... 127 रेंज (डिफ़ॉल्ट कॉन्फ़िगरेशन में)।

Integer.valueOf(127) == Integer.valueOf(127) 

लेकिन

Integer.valueOf(128) != Integer.valueOf(128) 

सामान्यतया आप का उपयोग करना चाहिए किसी भी वस्तुओं की तुलना करने के लिए विधि के बराबर होती है। ऑपरेटर == का उपयोग प्रदर्शन में सुधार के लिए किया जा सकता है, जब ऑब्जेक्ट के लिए अलग-अलग मानों की संख्या कम होती है। मैं इस विधि का उपयोग करने की अनुशंसा नहीं करता, जब तक कि आप जो भी कर रहे हैं उसमें 100% सुनिश्चित न हों।

+0

obvius बताते हुए प्रश्न को समझने के लिए धन्यवाद। तो मेरी खुद की अपरिवर्तनीय कक्षा, क्या यह बराबर के बदले == का उपयोग करना ठीक है अगर मैं आश्वस्त कर सकता हूं कि कोई डुप्लिकेट कभी मौजूद नहीं होगा। – CKing

+0

यदि आपकी फैक्ट्री विधि सही तरीके से काम करती है और कोई भी कुछ गंदे चीजें नहीं करेगा जैसे निजी कन्स्ट्रक्टर को प्रतिबिंब के माध्यम से कॉल करना, सबकुछ काम करना चाहिए। तो यदि आपके पास ऐसा करने के अच्छे कारण हैं, तो आगे बढ़ें। – vbezhenar

2

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

तो, आपके पास दो अपरिवर्तनीय आज्ञाएं हो सकती हैं, जो समान मान का प्रतिनिधित्व करती हैं (यानी, वे बराबर हैं ताकि aequequ (बी) सत्य लौटाएं) लेकिन यह वही उदाहरण नहीं है।

मैं तुम यहाँ के लिए एक छोटे से उदाहरण है:

 
public class MyPoint { 
    private int x; 
    private int y; 

    public MyPoint(int x, int y) { 
     this.x = x; 
     this.y = y; 
    } 

    public int getX() { 
     return x; 
    } 

    public int getY() { 
     return y; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (!(obj instanceof MyPoint)) 
      return false; 
     MyPoint p = (MyPoint) obj; 
     return this.x == p.x && this.y == p.y; 
    } 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     MyPoint p = new MyPoint(2, 2); 
     MyPoint q = new MyPoint(2, 2); 
     MyPoint r = q; 

     System.out.println(p == q); 
     System.out.println(p == r); 
     System.out.println(q == r); 
     System.out.println(p.equals(q)); 
     System.out.println(p.equals(r)); 
     System.out.println(q.equals(r)); 

    } 

}

उत्पादन होता है: झूठी झूठी सच सच सच सच

MyPoint अपरिवर्तनीय है। प्रारंभ होने के बाद आप इसके मूल्य/राज्य को बदल नहीं सकते हैं। लेकिन, जैसा कि आप देख सकते हैं, MyPoint की दो ऑब्जेक्ट बराबर हो सकती हैं, लेकिन हो सकता है कि वे एक ही उदाहरण न हों।

मुझे लगता है कि आपके मन में जो कुछ है, वह किसी प्रकार का फ्लाईवेट पैटर्न है, जहां ऑब्जेक्ट की हर संभव स्थिति के लिए केवल एक वस्तु मौजूद है। फ्लाईवेट का भी अर्थ है कि आमतौर पर उन आज्ञाओं को अपरिवर्तनीय माना जाता है।

+0

फ्लाईवेट संदर्भ के लिए धन्यवाद! – CKing