क्यों String.valueOf (नल) एक NullPointerException को फेंक देता है?


127

प्रलेखन के अनुसार, विधि String.valueOf(Object obj)रिटर्न:

यदि तर्क है null, तो एक स्ट्रिंग के बराबर "null"; अन्यथा, का मान obj.toString()लौटाया जाता है।

लेकिन जब मैं ऐसा करने की कोशिश करता हूं तो मैं कैसे आता हूं:

System.out.println("String.valueOf(null) = " + String.valueOf(null));

इसके बजाय एनपीई फेंकता है? (यदि आप विश्वास नहीं करते हैं तो इसे स्वयं आज़माएँ!)

    थ्रेड में अपवाद "मुख्य" java.lang.NullPointerException
    java.lang.String पर। (अज्ञात स्रोत)
    java.lang.String.valueOf (अज्ञात स्रोत) पर

यह कैसे हो रहा है? क्या दस्तावेज मेरे पास पड़ा है? यह जावा में एक प्रमुख बग है?

जवाबों:


201

समस्या यह है कि String.valueOfविधि अतिभारित है :

जावा विशिष्टता भाषा में कहा गया है कि इस तरह के मामलों में, सबसे विशिष्ट अधिभार चुना जाता है:

JLS 15.12.2.5 सबसे विशिष्ट तरीका चुनना

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

char[] -हैObject , लेकिन सभी ए - ए नहीं Object है char[] । इसलिए, char[]है और अधिक विशिष्ट से Object, और के रूप में जावा भाषा द्वारा निर्दिष्ट, String.valueOf(char[])अधिभार इस मामले में चुना जाता है।

String.valueOf(char[])सरणी को गैर- होने की उम्मीद है null, और जब nullसे इस मामले में दिया जाता है, तब यह फेंकता है NullPointerException

आसान "फिक्स" निम्नानुसार nullस्पष्ट Objectरूप से डालना है:

System.out.println(String.valueOf((Object) null));
// prints "null"

संबंधित सवाल


कहानी का नैतिक

कई महत्वपूर्ण हैं:

  • प्रभावी जावा 2 संस्करण, आइटम 41: विवेकपूर्ण तरीके से ओवरलोडिंग का उपयोग करें
    • सिर्फ इसलिए कि आप ओवरलोड कर सकते हैं, इसका मतलब यह नहीं है कि आपको हर बार करना चाहिए
    • वे भ्रम पैदा कर सकते हैं (खासकर अगर तरीके बेतहाशा अलग-अलग काम करते हैं)
  • अच्छी IDE का उपयोग करके, आप जांच सकते हैं कि संकलन के समय कौन सा अधिभार चुना गया है
    • ग्रहण के साथ, आप उपरोक्त अभिव्यक्ति पर माउस-होवर कर सकते हैं और देख सकते हैं कि वास्तव में , valueOf(char[])अधिभार का चयन किया गया है!
  • कभी-कभी आप स्पष्ट रूप से कास्ट करना चाहते हैं null(उदाहरण के लिए)

यह सभी देखें


कास्ट करने पर null

कम से कम दो स्थितियां हैं जहां nullविशिष्ट संदर्भ प्रकार के लिए स्पष्ट रूप से कास्टिंग आवश्यक है:

  • ओवरलोडिंग का चयन करने के लिए (जैसा कि ऊपर दिए गए उदाहरण में दिया गया है)
  • nullएक वार्ग पैरामीटर के लिए एकल तर्क के रूप में देने के लिए

उत्तरार्द्ध का एक सरल उदाहरण निम्नलिखित है:

static void vararg(Object... os) {
    System.out.println(os.length);
}

फिर, हमारे पास निम्नलिखित हो सकते हैं:

vararg(null, null, null); // prints "3"
vararg(null, null);       // prints "2"
vararg(null);             // throws NullPointerException!

vararg((Object) null);    // prints "1"

यह सभी देखें

संबंधित सवाल


5
एक और सुझाव: जब आप एक विधि को ओवरलोड करते हैं और एक तर्क को दो अधिभार (जैसे nullइस मामले में) पर बुलाया जा सकता है , तो सुनिश्चित करें कि दोनों अधिभार उस मूल्य के संबंध में एक ही कार्य करते हैं!
जोआचिम सॉउर

3
@ जोकिम: मैंने अभी-अभी आइटम को पढ़ा, और यह जानकर सुखद आश्चर्य हुआ कि इन दोनों विधियों पर स्पष्ट रूप से चर्चा की गई थी! बलोच एक कदम आगे चला गया और दावा है कि के बाद से String.valueOf(Object)और valueOf(char[])पूरी तरह से अलग चीजें वैसे भी (भले ही के कर nullया नहीं) है कि शायद वे पहली जगह में भार के नहीं होना चाहिए था।
पॉलीजेन लुब्रीकेंट 12

एक सवाल है ... यदि आपके पास एक विधि है जो एक वस्तु लौटाती है तो कथन return null;ठीक उसी तरह होगा जैसे return (Object) null;?
user972276

17

समस्या यह है कि आप कॉल कर रहे हैं String.valueOf(char[])और नहीं String.valueOf(Object)

इसका कारण यह है कि जावा हमेशा एक अतिभारित विधि के सबसे विशिष्ट संस्करण का चयन करेगा जो प्रदान किए गए मापदंडों के साथ काम करता है। nullएक Objectपैरामीटर के लिए एक वैध मूल्य है , लेकिन यह एक char[]पैरामीटर के लिए एक वैध मूल्य भी है ।

जावा को Objectसंस्करण का उपयोग करने के लिए , या तो nullएक चर के माध्यम से पास करें या ऑब्जेक्ट के लिए एक स्पष्ट डाली निर्दिष्ट करें:

Object o = null;
System.out.println("String.valueOf(null) = " + String.valueOf(o));
// or
System.out.println("String.valueOf(null) = " + String.valueOf((Object) null));

5

2003 में इस तरह से एक बग, संख्या 4867608 दर्ज की गई थी, जिसे इस स्पष्टीकरण के साथ "ठीक नहीं होगा" के रूप में हल किया गया था।

हम अनुकूलता की कमी के कारण इसे बदल नहीं सकते हैं। ध्यान दें कि यह सार्वजनिक स्थैतिक स्ट्रिंग valueOf (char data []) विधि है जिसे समाप्त किया जा रहा है और इसमें अशक्त तर्कों के लिए "null" के प्रतिस्थापन का उल्लेख नहीं है।

@ ###। ### 2003-05-23


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.