2013-07-09 15 views
12

का उपयोग करते समय मैं इस तरह मेरी जावा कोड लिखें:अजीब व्यवहार जब जावा त्रिगुट ऑपरेटर

Map<String, Long> map = new HashMap<>() 
Long number =null; 
if(map == null) 
    number = (long) 0; 
else 
    number = map.get("non-existent key"); 

एप्लिकेशन की उम्मीद के रूप में चलाता है, लेकिन जब मैं यह कर:

Map<String, Long> map = new HashMap<>(); 
Long number= (map == null) ? (long)0 : map.get("non-existent key"); 

मैं पर एक NullPointerException मिल दूसरी पंक्ति। डिबग सूचक java.lang.Thread कक्षा में इस विधि के लिए दूसरी पंक्ति से कूदता है:

/** 
    * Dispatch an uncaught exception to the handler. This method is 
    * intended to be called only by the JVM. 
    */ 
    private void dispatchUncaughtException(Throwable e) { 
     getUncaughtExceptionHandler().uncaughtException(this, e); 
    } 

यहाँ क्या हो रहा है? ये दोनों कोड पथ बिल्कुल बराबर नहीं हैं?


संपादित

मैं जावा 1.7 U25

+0

आप असंभव के लिए क्यों परीक्षण कर रहे हैं? आप स्वयं 'नक्शा' बनाते हैं; यदि यह 'शून्य' है, तो आपका रनटाइम सिस्टम टूटा हुआ है। चूंकि यह स्पष्ट रूप से आपके द्वारा किए जा रहे अन्य कार्यों का एक छोटा संस्करण है, मैं सुझाव दूंगा कि आप सुनिश्चित करें कि वस्तुओं को हमेशा प्रारंभ किया जाता है इसलिए आपको 'map == null' चेक नहीं करना है। चाबियाँ आपकी समस्या हैं। –

+0

@Eric Jablow यह मेरे कोड का एक सरलीकृत संस्करण है। प्रश्न में नक्शा वास्तव में किसी अन्य स्थान से पुनर्प्राप्त किया जा रहा है जहां वे मांग पर गतिशील रूप से बनाए गए हैं। यही कारण है कि चेक। यहां मैंने प्रारंभिकरण शामिल किया ताकि यह उन लोगों के लिए स्पष्ट हो जो उत्तर दे रहे हैं कि अगर मेरी समस्या – radiantRazor

+0

हो रही है तो सही-सही मामला निष्पादित नहीं किया जा रहा है। शायद किसी को तुरंत अपवाद फेंकना होगा यदि कोई आपके कोड पर 'शून्य' मानचित्र पास कर रहा था। या, यदि कोई आपके कोड में 'शून्य' में गुजरता है, तो अपना नक्शा इसके बजाय खाली स्थान पर सेट करें। –

उत्तर

15

वे बराबर नहीं हैं।

इस अभिव्यक्ति

(map == null) ? (long)0 : map.get("non-existent key"); 

के प्रकार long है, क्योंकि सच परिणाम टाइप long है।

कारण इस अभिव्यक्ति प्रकार long की है अनुभाग §15.25 of the JLS से है:

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

आप एक गैर existant कुंजी map रिटर्न null देखने है। तो, जावा इसे long पर अनबॉक्स करने का प्रयास कर रहा है। लेकिन यह null है। तो यह नहीं हो सकता है और आपको NullPointerException मिल सकता है। आप यह कहकर इसे ठीक कर सकते हैं:

Long number = (map == null) ? (Long)0L : map.get("non-existent key"); 

और फिर आप ठीक होंगे।

हालांकि, यहां,

if(map == null) 
    number = (long) 0; 
else 
    number = map.get("non-existent key"); 

number के बाद से Long के रूप में घोषित किया जाता है, कि एक long unboxing के लिए कभी नहीं होता है।

+0

उस स्थिति में, क्या पोस्टर 'लंबे समय' के बजाय 0 को 'लांग'' कास्टिंग करके टर्नरी ऑपरेटर का उपयोग कर सकता है? – MathSquared

+1

हां, उसे '0L' को' Long' पर डालना होगा। – jason

+2

वाह, जेएलएस में इतने सारे छिपे हुए कैच हैं। मेरा स्पष्ट अनुवर्ती प्रश्न यह होगा कि जेएलएस ने किस प्रकार को प्राचीन के रूप में अनुमानित करने के लिए परिभाषित किया है? यदि यह परिभाषित किया गया था कि प्रकार को ऑटोबॉक्स्ड प्रकार के रूप में अनुमानित किया जाना चाहिए, तो ऐसे नलपॉइंटर अपवादों से बचा जा सकता था। मैं इसे एक अलग सवाल के रूप में पूछने की कोशिश करूंगा – radiantRazor

3

यहाँ क्या हो रहा है उपयोग कर रहा हूँ? ये दोनों कोड पथ बिल्कुल समकक्ष नहीं हैं?

वे बराबर नहीं हैं; टर्नरी ऑपरेटर में कुछ चेतावनी हैं।

अगर सच त्रिगुट ऑपरेटर, (long) 0 का तर्क, आदिम प्रकार long की है। नतीजतन, अगर-झूठे तर्क Long से करने के लिए स्वचालित रूप से अनबॉक्स्ड हो जाएगा long (प्रति JLS §15.25 के रूप में):

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

हालांकि, इस तर्क null है (के बाद से अपने नक्शे स्ट्रिंग "non-existent key", get() रिटर्न null अर्थ शामिल नहीं है), तो एक NullPointerException unboxing प्रक्रिया के दौरान होता है।

+0

लेकिन if-true मान के प्रकार को प्रभावित करने वाले if-true मान का प्रकार क्यों है? क्या इसे एलएचएस के प्रकार से निर्धारित नहीं किया जाना चाहिए? – radiantRazor

+1

@radiantRazor संक्षेप में, क्योंकि इस तरह जेएलएस टर्नरी ऑपरेटर को परिभाषित करता है। – arshajii

0

मैंने ऊपर टिप्पणी की है कि वह mapnull कभी भी सुनिश्चित नहीं करता है, लेकिन यह टर्नरी समस्या से मदद नहीं करता है। एक व्यावहारिक मामले के रूप में, सिस्टम को आपके लिए काम करने देना आसान है। वह अपाचे कॉमन्स कलेक्शन 4 और इसकी DefaultedMap कक्षा का उपयोग कर सकता था।

import static org.apache.commons.collections4.map.DefaultedMap.defaultedMap; 

Map<String, Long> map = ...; // Ensure not null. 
Map<String, Long> dMap = defaultedMap(map, 0L); 

गूगल अमरूद कि जितना आसान लेना देना नहीं है, लेकिन एक Maps.transformValues() विधि के साथ map लपेट कर सकते हैं।

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