इंट से तुलना करने वाले इंट ने जावा में NullPointerException को क्यों फेंक सकते हैं?


81

इस स्थिति का निरीक्षण करना मेरे लिए बहुत उलझन की बात थी:

Integer i = null;
String str = null;

if (i == null) {   //Nothing happens
   ...                  
}
if (str == null) { //Nothing happens

}

if (i == 0) {  //NullPointerException
   ...
}
if (str == "0") { //Nothing happens
   ...
}

इसलिए, जैसा कि मुझे लगता है कि बॉक्सिंग ऑपरेशन को पहले निष्पादित किया गया है (यानी जावा से अंतर मान निकालने की कोशिश करता है null) और तुलनात्मक ऑपरेशन की प्राथमिकता कम है इसलिए अपवाद को फेंक दिया गया है।

सवाल यह है कि यह जावा में इस तरह से क्यों लागू किया जाता है? संदर्भों की तुलना करना बॉक्सिंग की उच्च प्राथमिकता क्यों है? या उन्होंने nullमुक्केबाजी से पहले सत्यापन को लागू क्यों नहीं किया ?

इस समय यह असंगत दिखता है जब NullPointerExceptionलिपटे आदिम के साथ फेंक दिया जाता है और इसे सच्चे ऑब्जेक्ट प्रकारों के साथ नहीं फेंका जाता है


यदि आपने str.equals ("0") किया तो आपको NullPointerException मिल जाएगी।
ऐश बर्लज़ेंको

== ऑपरेटर एक बार किसी भी परिस्थिति में एनपीई के खिलाफ बचत करता था। मेरे लिए यह सिर्फ एक और उदाहरण है जो दर्शाता है कि जावा में ऑटो बॉक्सिंग शुरू करने के लिए क्या बुरा विचार था। यह सिर्फ इतने सारे कारणों के लिए फिट नहीं है और इससे पहले ऐसा कुछ भी नहीं है। यह केवल कोड को छोटा कोड बनाता है जबकि यह बताता है कि वास्तव में क्या चल रहा है।
x4u

मेरे विचार 180 डिग्री अलग हैं। उन्हें हर जगह इस्तेमाल की जाने वाली आदिम वस्तुओं को शामिल नहीं करना चाहिए था। फिर कंपाइलर को ऑप्टिमाइज़ करें और प्रिमिटिव का उपयोग करें। फिर कोई भ्रम नहीं होगा।
जेजेकेज

जवाबों:


138

संक्षिप्त उत्तर

मुख्य बिंदु यह है:

  • == दो संदर्भ प्रकारों के बीच हमेशा संदर्भ तुलना होती है
    • अधिक बार नहीं, उदाहरण के लिए Integerऔर String, आप equalsइसके बजाय उपयोग करना चाहते हैं
  • == एक संदर्भ प्रकार और एक संख्यात्मक आदिम प्रकार के बीच हमेशा संख्यात्मक तुलना होती है
    • संदर्भ प्रकार को अनबॉक्सिंग रूपांतरण के अधीन किया जाएगा
    • अनबॉक्सिंग nullहमेशा फेंकता हैNullPointerException
  • जबकि जावा के लिए कई विशेष उपचार हैं String, यह वास्तव में एक आदिम प्रकार नहीं है

उपरोक्त कथन किसी भी मान्य जावा कोड के लिए हैं। इस समझ के साथ, आपके द्वारा प्रस्तुत स्निपेट में कोई असंगतता नहीं है।


दीर्घ उत्तर

यहाँ प्रासंगिक JLS अनुभाग हैं:

JLS 15.21.3 संदर्भ समानता ऑपरेटर ==और!=

यदि एक समतुल्य ऑपरेटर के संचालक दोनों संदर्भ प्रकार या अशक्त प्रकार के हैं, तो ऑपरेशन ऑब्जेक्ट समानता है।

यह निम्नलिखित बताते हैं:

Integer i = null;
String str = null;

if (i == null) {   // Nothing happens
}
if (str == null) { // Nothing happens
}
if (str == "0") {  // Nothing happens
}

दोनों ऑपरेंड संदर्भ प्रकार हैं, और इसीलिए ==संदर्भ समानता तुलना है।

यह भी निम्नलिखित बताते हैं:

System.out.println(new Integer(0) == new Integer(0)); // "false"
System.out.println("X" == "x".toUpperCase()); // "false"

के लिए ==संख्यात्मक समानता होने के लिए, संकार्य कम से कम एक एक अंकीय प्रकार होना चाहिए :

JLS 15.21.1 संख्यात्मक समानता ऑपरेटर ==और!=

यदि एक समानता ऑपरेटर के ऑपरेंड संख्यात्मक प्रकार के दोनों होते हैं , या एक संख्यात्मक प्रकार का होता है और दूसरा संख्यात्मक प्रकार के लिए परिवर्तनीय होता है, तो ऑपरेंड्स पर बाइनरी न्यूमेरिक प्रमोशन किया जाता है। यदि ऑपरेंड का प्रचारित प्रकार intया है long, तो एक पूर्णांक समानता परीक्षण किया जाता है; यदि पदोन्नत प्रकार float or double` है, तो एक फ्लोटिंग-पॉइंट समानता परीक्षण किया जाता है।

ध्यान दें कि बाइनरी न्यूमेरिक प्रमोशन वैल्यू सेट रूपांतरण और अनबॉक्सिंग रूपांतरण करता है।

यह बताते हैं:

Integer i = null;

if (i == 0) {  //NullPointerException
}

यहाँ प्रभावी जावा 2 संस्करण से एक अंश है , आइटम 49: बॉक्सिंग आदिम के लिए प्राथमिकताओं को प्राथमिकता दें :

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

ऐसी जगहें हैं जहां आपके पास बॉक्सिंग प्राइमेटिक्स का उपयोग करने के अलावा कोई विकल्प नहीं है, जैसे जेनेरिक, लेकिन अन्यथा आपको गंभीरता से विचार करना चाहिए कि क्या बॉक्सेड प्राइमेटिव्स का उपयोग करने का निर्णय उचित है।

संदर्भ

संबंधित सवाल

संबंधित सवाल


2
के रूप में क्यों someRef == 0 हमेशा अंकीय तुलना है, यह एक बहुत ध्वनि पसंद है दो बॉक्स्ड पुरातन के संदर्भ की तुलना लगभग है के बाद से हमेशा एक प्रोग्रामर त्रुटि। इस मामले में तुलना करने के लिए डिफ़ॉल्ट करना बेकार होगा।
मार्क पीटर्स

3
क्यों नहीं संकलक अभिव्यक्ति की जगह लेंगे (myInteger == 0)साथ (myInteger != null && myInteger == 0)इस बॉयलरप्लेट अशक्त-चेकिंग कोड लिखने के लिए डेवलपर पर निर्भर रहने के बजाय? IMO मुझे जांचने में सक्षम होना चाहिए if (myBoolean)और इसका मूल्यांकन करना चाहिए कि trueकेवल और केवल अगर अंतर्निहित मूल्य विशेष रूप से है true- तो मुझे पहले जांच नहीं करनी चाहिए।
जोश एम।


4
if (i == 0) {  //NullPointerException
   ...
}

मैं एक पूर्णांक हूं और 0 एक ऐसा उदाहरण है जो वास्तव में किया जाता है, ऐसा कुछ है

i.intValue() == 0

और यह nullPointer का कारण बनता है क्योंकि i null है। स्ट्रिंग के लिए हमारे पास यह ऑपरेशन नहीं है, इसलिए कोई अपवाद नहीं है।


4

जावा के निर्माता परिभाषित कर सकते हैं== विभिन्न प्रकार के ऑपरेंड पर सीधे कार्य करने के ऑपरेटर को , जिस स्थिति में Integer I; int i;यह तुलना दी I==i;जा सकती थी कि प्रश्न "क्या किसके मूल्य का Iसंदर्भ रखता Integerहै i?" - एक ऐसा प्रश्न जिसका उत्तर बिना कठिनाई के दिया जा सकता है ? Iअशक्त होने पर भी । दुर्भाग्य से, जावा सीधे जांच नहीं करता है कि क्या विभिन्न प्रकार के ऑपरेंड समान हैं; इसके बजाय, यह जाँचता है कि क्या भाषा या तो ऑपरेंड के प्रकार को दूसरे के प्रकार में परिवर्तित करने की अनुमति देती है और - यदि वह ऐसा करती है - परिवर्तित ऑपरेंड की तुलना गैर-रूपांतरित एक से करती है। इस तरह के व्यवहार का मतलब है कि चर के लिए x, yऔर zप्रकार के कुछ संयोजनों के साथ, यह संभव है करने के लिए है x==yऔर y==zलेकिनx!=z[जैसे x = 16777216f y = 16777216 z = 16777217]। इसका यह भी अर्थ है कि तुलना I==iका अनुवाद "कन्वर्ट आई टू ए int, अगर यह अपवाद नहीं है, तो इसकी तुलना करें i।"


+1: वास्तव में ओपी के इस सवाल का जवाब देने की कोशिश कर रहा है कि "ऐसा क्यों है?"
मार्टिग्न कोर्टको 20

1
@MartijnCourteaux: कई भाषाएं केवल मिलान प्रकारों के ऑपरेंड के लिए ऑपरेटरों को परिभाषित करने लगती हैं, और मानती हैं कि यदि कोई टी कभी भी यू के लिए अनुमानित रूप से परिवर्तनीय है, तो इस तरह के निहितार्थ को बिना किसी शिकायत के किसी भी समय स्वीकार किया जा सकता है, लेकिन यू को स्वीकार नहीं किया जा सकता है। यह नहीं इस तरह के व्यवहार के लिए, एक भाषा में निर्धारित कर सकते थे ==इस तरह से है कि अगर सभी मामलों में जहां में x==y, y==zहै, और x==zबिना किसी शिकायत के सभी संकलन, तीन की तुलना एक तुल्यता संबंध के रूप में व्यवहार करेगा। उत्सुक है कि डिजाइनर सभी प्रकार की फैंसी भाषा सुविधाओं को धक्का देते हैं, लेकिन स्वयंसिद्ध अनुपालन की उपेक्षा करते हैं।
सुपरकैट

1

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

चूँकि यह संभव नहीं है (यह आप के रूप में पंक्तिबद्ध है) शून्य NullPointerExceptionहै।


1

में i == 0जावा ऑटो unboxing करने की कोशिश और एक संख्यात्मक तुलना करना होगा (यानी "द्वारा संदर्भित आवरण वस्तु में संग्रहीत मूल्य है iमूल्य के रूप में ही0 ?")।

के बाद से iहै nullunboxing एक फेंक होगाNullPointerException

तर्क इस प्रकार है:

JLS का पहला वाक्य § 15.21.1 न्यूमेरिकल इक्वैलिटी ऑपरेटर्स == और! = इस तरह से पढ़ता है:

यदि एक समानता ऑपरेटर के ऑपरेंड संख्यात्मक प्रकार के दोनों होते हैं, या एक संख्यात्मक प्रकार का होता है और दूसरा संख्यात्मक प्रकार के लिए परिवर्तनीय (to5.1.8) होता है, तो द्विआधारी संख्यात्मक पदोन्नति ऑपरेंड (is5.6.2) पर की जाती है।

स्पष्ट रूप iसे एक संख्यात्मक प्रकार के लिए परिवर्तनीय है और 0एक संख्यात्मक प्रकार है, इसलिए बाइनरी न्यूमेरिक प्रचार ऑपरेंड पर किया जाता है।

§ 5.6.2 बाइनरी न्यूमेरिक प्रमोशन कहता है (अन्य बातों के अलावा):

यदि कोई भी ऑपरेंड एक संदर्भ प्रकार का है, तो अनबॉक्सिंग रूपांतरण (.85.1.8) किया जाता है।

Things 5.1.8 अनबॉक्सिंग रूपांतरण कहता है (अन्य बातों के अलावा):

यदि r शून्य है, तो अनबॉक्सिंग रूपांतरण फेंकता है aNullPointerException


0

बस एक विधि लिखें और इसे NullPointerException से बचने के लिए कॉल करें।

public static Integer getNotNullIntValue(Integer value)
{
    if(value!=null)
    {
        return value;
    }
    return 0;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.