2013-02-06 21 views
6
public class Test { 
    public static final Double DEFAULT_DOUBLE = 12.0; 
    public static final Long DEFAULT_LONG = 1L; 

    public static Double convertToDouble(Object o) { 
     return (o instanceof Number) ? ((Number) o).doubleValue() 
       : DEFAULT_DOUBLE; 
    } 

    public static Long convertToLong(Object o) { 
     return (o instanceof Number) ? ((Number) o).longValue() : DEFAULT_LONG; 
    } 

    public static void main(String[] args){ 
     System.out.println(convertToDouble(null) == DEFAULT_DOUBLE); 
     System.out.println(convertToLong(null) == DEFAULT_LONG); 
    } 
} 
+2

यहाँ पुनर्त्पादित। यह अजीब है। हां, ओपी को 'बराबर() 'का उपयोग करना चाहिए, लेकिन इन चीजों के साथ खेलना हमेशा दिलचस्प होता है। – Mysticial

+0

* गायब ब्रैकेट्स। और हाँ, कभी-कभी सच, दूसरों को झूठा। सिवाय इसके कि नल कभी-कभी 0 (या शून्य का गुच्छा) होता है, जो एक संख्या है। –

+0

@Mysticial यदि आपको अजीब (और अभी तक अनिश्चित) सामान पसंद है: http://stackoverflow.com/questions/14624365/immutability-and-reordering – assylias

उत्तर

8

संपादित

त्रिगुट ऑपरेटर some type conversions under the hood करता है। आपके मामले में आप पुरातन और आवरण प्रकार, जिस स्थिति में आवरण प्रकार unboxed हो जाता है मिश्रण कर रहे हैं, तो त्रिगुट ऑपरेटर का परिणाम "फिर से बॉक्सिंग" है:

दूसरे और तीसरे ऑपरेंड में से एक की है आदिम प्रकार टी, और अन्य प्रकार के मुक्केबाजी रूपांतरण को लागू करने का परिणाम है (§5.1.7) टी करने के लिए, तो सशर्त अभिव्यक्ति के प्रकार टी


तो अपने कोड अनिवार्य रूप से किया जाता है समकक्ष (टाइपो के अलावा longValuedoubleValue होना चाहिए):

public static void main(String[] args){ 
    Double d = 12.0; 
    System.out.println(d == DEFAULT_DOUBLE); 

    Long l = 1L; 
    System.out.println(l == DEFAULT_LONG); 
} 

कुछ मूल्यों पर लंबे मूल्यों को कैश किया जा सकता है और == तुलना इसलिए सच हो सकती है। यदि आपने equals के साथ सभी तुलना की है तो आपको दोनों मामलों में true मिलेगा।

ध्यान दें कि अगर आप public static final Long DEFAULT_LONG = 128L; का उपयोग करें और प्रयास करें:

Long l = 128L; 
System.out.println(l == DEFAULT_LONG); 

यह शायद, झूठी प्रिंट होगा क्योंकि लंबे समय मूल्यों आम तौर पर -128 और केवल 127 के बीच कैश नहीं किया जाता।

नोट: JLS की आवश्यकता है कि -127 और 128 के बीच char, byte और int मूल्यों कैश हो लेकिन long के बारे में कुछ नहीं कहा। तो आपका कोड वास्तव में एक अलग JVM पर दो बार झूठा प्रिंट कर सकता है।

+0

तो आप कह रहे हैं कि निरंतर प्रचार ऑटो-मुक्केबाजी द्वारा नए में किया जाता है वस्तु। तो उन्हें दोनों झूठी वापसी करनी चाहिए। लेकिन फिर पूर्णांक छोटे मानों के लिए कैश किए जाते हैं, ताकि यह सच हो जाए? – Mysticial

+0

@ मिस्टिकिक मूल रूप से यदि आप -127/+ 128 रेंज (जैसे 'इंटीजर i = 123;') में चार, बाइट या int पर मुक्केबाजी का उपयोग करते हैं, तो आपको हमेशा एक ही उदाहरण प्राप्त करने की गारंटी दी जाती है। यह लॉन्ग के लिए आवश्यक नहीं है लेकिन मेरे जेवीएम (ओरेकल जेडीके 7u11) पर मामला प्रतीत होता है। तो नहीं, मैं यह नहीं कह रहा हूं कि व्यवहार इंटीग्रियों को कैश किया जा रहा है। – assylias

+0

हाँ, कैशिंग भाग मुझे पता है क्योंकि मैंने एसओ पर पहले देखा है। जब मैंने सवाल देखा, तो मुझे वास्तव में दोनों सच होने की उम्मीद थी क्योंकि वे दोनों मूल वस्तु के संदर्भ होंगे। लेकिन यहां मुझे लगता है कि यह मामला नहीं है। कंपाइलर/जेवीएम वास्तव में नई वस्तुएं बना रहा है (क्यों?)। – Mysticial

4

अजीब व्यवहार को समझने के लिए, आप अलग लेने के लिए यह क्या करता है की जरूरत है:

(o instanceof Number) ? ((Number) o).longValue() : DEFAULT_LONG 

क्या हम यहाँ है विधि के लिए एक कॉल है कि एक long देता है, और Long का एक उदाहरण है। दो अलग प्रकार। हालांकि सशर्त ऑपरेटर ? को एक प्रकार का उत्पादन करने की आवश्यकता है; या तो long या Long। और ऐसा करने के लिए, या तो दूसरा ऑपरेंड बॉक्स किया जाना चाहिए या तीसरा ऑपरेंड अनबॉक्स होना चाहिए।

इस मामले में, जेएलएस का कहना है कि तीसरा ऑपरेंड अनबॉक्स किया जाना चाहिए। JLS 15.25

"दूसरे और तीसरे ऑपरेंड में से एक आदिम प्रकार टी की है, और अन्य के प्रकार, टी करने के लिए मुक्केबाजी रूपांतरण (§5.1.7) लागू तो के प्रकार का परिणाम है तो सशर्त अभिव्यक्ति टी है। "

और इसका मतलब है कि आपके स्थिरांक को अनबॉक्स किया जा रहा है और फिर फिर से बॉक्स किया गया है।

अब मुक्केबाजी एक प्राचीन प्रकार बॉक्स बॉक्स प्रकार valueof() विधि को कॉल करके किया जाता है। और ये विधियां बेस प्रकार के आधार पर थोड़ा अलग चीजें करती हैं।

  • एक चल बिन्दु प्रकार के लिए, valueof हमेशा एक नई वस्तु
  • बनाता है एक अभिन्न प्रकार के लिए, valueof विधि कभी कभी एक नई वस्तु बनाता है, और कभी कभी किसी मौजूदा ऑब्जेक्ट देता है।

और बाद वाला यह हो रहा है कि यहां क्या हो रहा है। Long.valueof(1L) हमेशा एक ही मूल्य लौटा रहा है, और == के साथ तुलना true दे रही है।


दो "फिक्स" वहाँ रहे हैं ... यह सोचते हैं आप इसे ठीक करना चाहते हैं:

  • दोनों शाखाओं में एक return के साथ एक if/else साथ त्रिगुट ऑपरेटर बदलें।
  • कास्ट दूसरे संकार्य यह मजबूर करने के लिए बॉक्सिंग की जानी चाहिए:

    return (o instanceof Number) ? 
         (Long) ((Number) o).longValue() : DEFAULT_LONG; 
    
+0

आप सही हैं, धन्यवाद। –

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