2013-08-23 13 views
5

मैंने हाल ही में कोड के निम्नलिखित दो स्निपेट चलाने की कोशिश की और आउटपुट में आश्चर्यचकित हुआ।शॉर्ट सर्किट बूलियन अभिव्यक्तियों में अनबॉक्सिंग कैसे काम करता है?

पहले:

// ... 
System.out.println((Boolean)null || true); 
// ... 

दूसरा:

// ... 
System.out.println((Boolean)null || false); 
// ... 

निम्नलिखित उत्पादन में पहला उदाहरण परिणाम: निम्न उत्पादन में
सच

दूसरे उदाहरण के परिणाम:
थ्रेड "मुख्य" जावा में अपवाद a.lang.NullPointerException
      com.blah.main पर (SanityCheck.java:26)

मैं करूंगा है सोचा दोनों उदाहरण, एक नल पॉइंटर एक्सेप्शन में परिणाम चाहिए के रूप में किसी भी छोटे-सर्किटिंग लागू किया जाता है बाईं दाहिनी ओर। बूलियन से बूलियन को अनबॉक्स करने का प्रयास तार्किक के दूसरी तरफ से असफल होना चाहिए था या विचार किया गया था।

क्या कोई इस असंगत व्यवहार को समझा सकता है?

+0

यह व्यवहार [जेएलएस] (http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.24) के साथ असंगत प्रतीत होता है "रन टाइम पर, बाएं - ऑपरेंड अभिव्यक्ति का मूल्यांकन पहले किया जाता है; यदि परिणाम में बूलियन टाइप किया गया है, तो इसे अनबॉक्सिंग रूपांतरण के अधीन किया जाता है " –

+2

SanityCheck.java – arynaq

उत्तर

2

मैं इसमें एक जैब ले जाऊंगा। चूंकि कंपाइलर दो बयानों की व्याख्या करने का प्रयास करता है, मुख्य अंतर यह है कि दाहिने तरफ सही के साथ कथन बाएं हाथ के बूलियन के साथ गणना करने की आवश्यकता नहीं है, जबकि दाईं तरफ झूठ के साथ कथन है।

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

+0

यह एक अच्छा जवाब है, लेकिन मैंने सोचा कि कोई भी छोटा सर्किटिंग बाएं से दाएं हो गया है। यदि बाएं ऑपरेंड एक या में सही है, तो सही ऑपरेंड का मूल्यांकन नहीं किया जाता है। इसी प्रकार, यदि बाएं ऑपरेंड और यह एक में सही है, तो सही ऑपरेंड का मूल्यांकन नहीं किया जाता है।मुझे लगता है कि यह संकलक द्वारा कुछ अनुकूलन हो सकता है, इसलिए मैं कक्षा फ़ाइल को डीकंपाइल करने का प्रयास करूंगा। – studro

+0

मुझे लगता है कि मैंने जो लिखा है उसे मैंने गलत तरीके से पढ़ा है - शॉर्ट सर्किटिंग भी लागू नहीं है क्योंकि यह संकलन समय पर अनुकूलित है। सटीक। – studro

+0

सही! कास्टिंग पास, और सही पास। फिर सत्य की कोई आवश्यकता नहीं है या * क्योंकि यह हमेशा सत्य रहेगा – user1549672

4

मैंने जेएडी के माध्यम से कक्षा फ़ाइल को चलाने के लिए यह देखने के लिए अनुकूलित किया कि अनुकूलित कोड कैसा दिखता है।

// ... 
System.out.println(true); 
// ... 

झूठे मामले के लिए:: सच मामले के लिए

// ... 
System.out.println(null.booleanValue()); 
// ... 
1

मैं अपने परिणामों को पुन: पेश नहीं कर सकते। मैं वास्तव में दोनों मामलों के लिए एनपीई मिलता है।

जेएलएस के अनुसार, बाएं हाथ के ऑपरेंड अभिव्यक्ति का हमेशा मूल्यांकन किया जाता है। जब (Boolean)null का मूल्यांकन किया जाता है, तो एक शून्य बूलियन ऑब्जेक्ट पर एक ऑटो अनबॉक्सिंग किया जाता है। विशेष रूप से, अंतर्निहित कोड null.booleanValue() एनपीई पैदा कर रहा है।

+1

आपको सही मामले के लिए एनपीई नहीं मिलना चाहिए। (बूलियन) नल अपने आप ठीक है। यहां तक ​​कि यदि इसका मूल्यांकन पहले किया जाता है, तो उसे नलपोइंटर अपवाद नहीं फेंकना चाहिए। – user1549672

+0

@ user1549672 यह वास्तव में मेरे साथ हो रहा है, इसलिए मैं अभी भी समस्या का पता लगाने की कोशिश कर रहा हूं। क्या परिणाम जेडीके संस्करण पर निर्भर करता है जिसका मैं उपयोग कर रहा हूं? –

+0

मुझे यकीन नहीं है। आप किस संस्करण पर चल रहे हैं? – user1549672

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