NullPointerException क्या है, और मैं इसे कैसे ठीक करूँ?


210

अशक्त सूचक अपवाद ( java.lang.NullPointerException) क्या हैं और उनके कारण क्या हैं?

कारण निर्धारित करने के लिए किन तरीकों / साधनों का उपयोग किया जा सकता है ताकि आप कार्यक्रम को समय से पहले समाप्त करने से अपवाद को रोक सकें?

जवाबों:


3764

जब आप एक संदर्भ चर (यानी एक वस्तु) घोषित करते हैं तो आप वास्तव में एक ऑब्जेक्ट के लिए एक पॉइंटर बना रहे हैं। निम्नलिखित कोड पर विचार करें जहां आप आदिम प्रकार का एक चर घोषित करते हैं int:

int x;
x = 10;

इस उदाहरण में, चर xएक है intऔर जावा इसे आपके लिए इनिशियलाइज़ करेगा 0। जब आप इसे 10दूसरी पंक्ति का मान प्रदान करते हैं, तो आपका मान 10उस मेमोरी लोकेशन में लिखा जाता है, जिसके द्वारा संदर्भित किया जाता है x

लेकिन, जब आप एक संदर्भ प्रकार घोषित करने की कोशिश करते हैं , तो कुछ अलग होता है। निम्नलिखित कोड लें:

Integer num;
num = new Integer(10);

पहली पंक्ति एक चर नाम की घोषणा करती है num, लेकिन इसमें वास्तव में एक आदिम मूल्य नहीं होता है। इसके बजाय, इसमें एक सूचक होता है (क्योंकि प्रकार Integerजो एक संदर्भ प्रकार है)। चूँकि आपने अभी तक यह नहीं बताया है कि जावा nullकिस ओर इशारा करता है, जिसका अर्थ है " मैं कुछ नहीं करने का इशारा कर रहा हूँ "।

दूसरी पंक्ति में, newकीवर्ड का उपयोग ऑब्जेक्ट के प्रकार (या बनाने) के लिए किया जाता है Integerऔर पॉइंटर चर numको उस Integerऑब्जेक्ट को सौंपा जाता है ।

ऐसा NullPointerExceptionतब होता है जब आप एक चर घोषित करते हैं, लेकिन एक वस्तु नहीं बनाते हैं और चर की सामग्री का उपयोग करने की कोशिश करने से पहले चर को निर्दिष्ट करते हैं (जिसे डेरेफेरिंग कहा जाता है )। तो आप एक ऐसी चीज की ओर इशारा कर रहे हैं जो वास्तव में मौजूद नहीं है।

डेरेफ्रेंसिंग आमतौर पर .एक विधि या क्षेत्र का उपयोग [करने के लिए , या किसी सरणी को अनुक्रमित करने के लिए उपयोग करते समय होता है ।

यदि आप numउस वस्तु को बनाने से पहले विचलन करने का प्रयास करते हैं जो आपको मिलती है NullPointerException। सबसे तुच्छ मामलों में, कंपाइलर समस्या को पकड़ लेगा और आपको बता देगा कि " num may not have been initialized," लेकिन कभी-कभी आप कोड लिख सकते हैं जो सीधे ऑब्जेक्ट नहीं बनाता है।

उदाहरण के लिए, आपके पास एक विधि हो सकती है:

public void doSomething(SomeObject obj) {
   //do something to obj
}

जिस स्थिति में, आप ऑब्जेक्ट नहीं बना रहे हैं obj, बल्कि यह मानते हुए कि doSomething()विधि को कॉल करने से पहले बनाया गया था। ध्यान दें, इस तरह से विधि को कॉल करना संभव है:

doSomething(null);

जो मामले में, objहै null। यदि विधि को पास-इन ऑब्जेक्ट के लिए कुछ करने का इरादा है, तो इसे फेंकना उचित है NullPointerExceptionक्योंकि यह एक प्रोग्रामर त्रुटि है और प्रोग्रामर को डीबगिंग उद्देश्यों के लिए उस जानकारी की आवश्यकता होगी। कृपया अपवाद संदेश में ऑब्जेक्ट चर का नाम शामिल करें, जैसे

Objects.requireNonNull(a, "a");

वैकल्पिक रूप से, ऐसे मामले हो सकते हैं जहां विधि का उद्देश्य केवल ऑब्जेक्ट में पारित होने पर काम करना नहीं है, और इसलिए एक शून्य पैरामीटर स्वीकार्य हो सकता है। इस मामले में, आपको अशक्त पैरामीटर की जांच करने और अलग तरह से व्यवहार करने की आवश्यकता होगी । आपको यह भी प्रलेखन में स्पष्ट करना चाहिए। उदाहरण के लिए, के doSomething()रूप में लिखा जा सकता है:

/**
  * @param obj An optional foo for ____. May be null, in which case 
  *  the result will be ____.
  */
public void doSomething(SomeObject obj) {
    if(obj == null) {
       //do something
    } else {
       //do something else
    }
}

अंत में, स्टैक ट्रेस का उपयोग करके अपवाद और कारण को कैसे इंगित करें

कारण निर्धारित करने के लिए किन तरीकों / साधनों का उपयोग किया जा सकता है ताकि आप कार्यक्रम को समय से पहले समाप्त करने से अपवाद को रोक सकें?

सोनबर फाइंडबग्स के साथ एनपीई का पता लगा सकता है। क्या सोनार JVM के कारण शून्य सूचक अपवादों को पकड़ सकता है


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

104
मैं इस पोस्ट के बारे में एक टिप्पणी जोड़ते हुए बताऊंगा कि ऑटोबॉक्सिंग का उपयोग करते समय आदिमों को असाइनमेंट भी NPEs का कारण बन सकता है: int a=bअगर b एक है तो NPE फेंक सकता है Integer। ऐसे मामले हैं जहां यह डिबग करने के लिए भ्रमित है।
साइमन फिशर

58
क्या वेब ब्राउजर से वेब पर एनपीई द्वारा फेंके गए एनपीई को पकड़ना संभव है? क्या यह वेब ब्राउजर से व्यू पेज सोर्स में दिखाई देगा ..
सिड

76
हाँ जाँच करें कि क्या वस्तु इस पर एक विधि लागू करने से पहले अशक्त के बराबर है या एक चर का उपयोग करने की कोशिश कर सकती है। आपके कोड को संरचित करने में कुछ समय अशक्त सूचक अपवाद से बचने में मदद कर सकता है। उदाहरण के लिए जब एक निरंतर स्ट्रिंग के साथ एक इनपुट स्ट्रिंग की जाँच की जा रही है, तो आपको यहाँ की तरह लगातार स्ट्रिंग के साथ शुरू करना चाहिए: यदि ("SomeString" .equals (inputString)) {} // भले ही inputString शून्य है कोई अपवाद नहीं फेंका गया है। तो कुछ चीजें हैं जो आप सुरक्षित होने की कोशिश करने के लिए कर सकते हैं।
रोज़

78
NullPointerExceptionअपने कोड में समस्याओं से बचने का एक अतिरिक्त तरीका उपयोग @Nullableऔर @NotNullएनोटेशन है। निम्नलिखित उत्तर में इस पर अधिक जानकारी है। हालाँकि यह उत्तर विशिष्ट रूप से IntelliJ IDE के बारे में है, यह अन्य उपकरणों पर भी लागू होता है क्योंकि यह टिप्पणियों से स्पष्ट है। (BTW मैं सीधे इस जवाब को संपादित करने की अनुमति नहीं है, शायद लेखक इसे जोड़ सकते हैं?)
अर्जन मेल्स

879

NullPointerExceptions अपवाद हैं जो तब होते हैं जब आप एक संदर्भ का उपयोग करने की कोशिश करते हैं जो स्मृति (शून्य) में कोई स्थान नहीं बताता है, क्योंकि यह एक ऑब्जेक्ट को संदर्भित कर रहा था। अशक्त संदर्भ पर एक विधि को कॉल करना या अशक्त संदर्भ के एक क्षेत्र तक पहुंचने की कोशिश करना एक ट्रिगर होगा NullPointerException। ये सबसे आम हैं, लेकिन अन्य तरीके NullPointerExceptionjavadoc पेज पर सूचीबद्ध हैं ।

संभवतया सबसे तेज उदाहरण कोड मैं यह बता सकता हूं NullPointerException:

public class Example {

    public static void main(String[] args) {
        Object obj = null;
        obj.hashCode();
    }

}

पहली पंक्ति के अंदर main, मैं स्पष्ट रूप से इसके बराबर Objectसंदर्भ सेट कर रहा हूं । इसका मतलब है कि मेरे पास एक संदर्भ है, लेकिन यह किसी भी वस्तु की ओर इशारा नहीं कर रहा है। उसके बाद, मैं संदर्भ का इलाज करने की कोशिश करता हूं, हालांकि यह उस पर एक विधि को कॉल करके किसी ऑब्जेक्ट को इंगित करता है। इसका परिणाम यह होता है कि उस स्थान पर निष्पादित करने के लिए कोई कोड नहीं है जो संदर्भ इंगित कर रहा है।objnullNullPointerException

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


49
मुझे समझ में आया कि आपने वहां जो कुछ भी लिखा था, लेकिन केवल इसलिए कि मैं थोड़ी देर के लिए कोडिंग कर रहा हूं और जानता हूं कि एक 'पॉइंटर' और 'रेफरेंस' क्या हैं (और उस मामले के लिए क्या अशक्त है)। जब मैं इस तरह से स्पष्टीकरण में सही गोता लगाने की कोशिश करता हूं, तो मेरे छात्र मेरी ओर देखते हैं, क्योंकि पर्याप्त पृष्ठभूमि नहीं है।
mmr

33
@ मिमी: प्रतिक्रिया के लिए धन्यवाद, आप एक वैध बिंदु बनाते हैं। यह इंटरनेट पर वास्तव में न्याय करना मुश्किल है कि कोई व्यक्ति कहां है, और स्पष्टीकरण शुरू करना किस स्तर पर सुरक्षित है। मैं इसे फिर से संशोधित करने का प्रयास करूंगा।
छिपकली

22
व्यवहार में NullPointerException प्राप्त करने का एक अधिक सामान्य तरीका इस तरहnull से उपयोग करने से पहले किसी अन्य के लिए किसी सदस्य चर को स्पष्ट रूप से प्रारंभ करना भूल जाएगा । स्थानीय चर के साथ, संकलक इस त्रुटि को पकड़ लेगा, लेकिन इस मामले में ऐसा नहीं है। शायद यह आपके उत्तर के लिए एक उपयोगी जोड़ बना देगा?
इल्मरी करोनें

6
@ ईजेपी मुझे लगता है कि आपके अंक वैध हैं, इसलिए मैंने उत्तर को स्पष्ट करने और 'बिंदुओं को शून्य' कहने से बचने के लिए अपडेट किया है जहां उसने किया था।
स्टीव पॉवेल

5
@StevePowell मैंने बहुत पहले संकेत दिया था कि मैं अपना जवाब बदलना नहीं चाहता था। कृपया मूल लेखक के इरादे का सम्मान करें।
को छिपकली

696

NullPointerException क्या है?

शुरू करने के लिए एक अच्छी जगह JavaDocs है । उनके पास यह कवर है:

जब कोई एप्लिकेशन किसी ऐसी स्थिति में नल का उपयोग करने का प्रयास करता है, जहां ऑब्जेक्ट की आवश्यकता होती है। इसमें शामिल है:

  • अशक्त वस्तु का उदाहरण विधि कहलाना।
  • किसी अशक्त वस्तु के क्षेत्र में पहुँच या संशोधन।
  • अशक्त की लंबाई लेते हुए जैसे कि यह एक सरणी थी।
  • नल के स्लॉट को एक्सेस करना या संशोधित करना जैसे कि वह एक सरणी हो।
  • शून्य को फेंकना जैसे कि यह एक फेंकने योग्य मूल्य था।

नल ऑब्जेक्ट के अन्य अवैध उपयोगों को इंगित करने के लिए अनुप्रयोगों को इस वर्ग के उदाहरणों को फेंकना चाहिए।

यह भी मामला है कि यदि आप के साथ एक अशक्त संदर्भ का उपयोग करने का प्रयास करते हैं synchronized, तो यह भी इस अपवाद को फेंक देगा, जेएलएस के अनुसार :

SynchronizedStatement:
    synchronized ( Expression ) Block
  • अन्यथा, यदि अभिव्यक्ति का मूल्य शून्य है, तो एक NullPointerExceptionफेंक दिया जाता है।

मैं इसे कैसे ठीक करूं?

तो आप ए NullPointerException। इसे ठीक कैसे कर सकते हैं? चलो एक सरल उदाहरण लेते हैं जो फेंकता है NullPointerException:

public class Printer {
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public void print() {
        printString(name);
    }

    private void printString(String s) {
        System.out.println(s + " (" + s.length() + ")");
    }

    public static void main(String[] args) {
        Printer printer = new Printer();
        printer.print();
    }
}

शून्य मानों को पहचानें

पहला चरण वास्तव में पहचान रहा है कि कौन से मूल्य अपवाद का कारण बन रहे हैं । इसके लिए हमें कुछ डीबगिंग करने की जरूरत है। स्टैकट्रेस पढ़ना सीखना महत्वपूर्ण है । यह आपको दिखाएगा कि अपवाद कहाँ फेंका गया था:

Exception in thread "main" java.lang.NullPointerException
    at Printer.printString(Printer.java:13)
    at Printer.print(Printer.java:9)
    at Printer.main(Printer.java:19)

यहाँ, हम देखते हैं कि अपवाद पंक्ति 13 ( printStringविधि में) पर फेंका गया है । रेखा को देखें और जांचें कि लॉगिंग स्टेटमेंट जोड़कर या डीबगर का उपयोग करके कौन से मान शून्य हैं । हमें पता चलता है कि sयह अशक्त है, और इस lengthपर विधि को कॉल करना अपवाद को फेंकता है। हम देख सकते हैं कि प्रोग्राम को अपवाद को फेंकना बंद हो जाता है जब s.length()विधि से हटा दिया जाता है।

ट्रेस जहां इन मूल्यों से आते हैं

अगली जाँच करें कि यह मान कहाँ से आया है। विधि की कॉल का पालन करके, हम देखते हैं कि sसाथ में पारित हो जाता है printString(name)में print()विधि, और this.nameरिक्त है।

ट्रेस जहां इन मूल्यों को सेट किया जाना चाहिए

कहां this.nameसेट है? में setName(String)विधि। कुछ और डीबगिंग के साथ, हम देख सकते हैं कि इस पद्धति को बिल्कुल नहीं कहा जाता है। अगर विधि बुलाया गया था, जांच करना न भूलें आदेश है कि इन तरीकों कहा जाता है और सेट विधि नहीं बुलाया जाता है के बाद प्रिंट विधि।

यह हमें एक समाधान देने के लिए पर्याप्त है: कॉल करने printer.setName()से पहले एक कॉल जोड़ें printer.print()

अन्य सुधार

चर का डिफ़ॉल्ट मानsetName हो सकता है (और इसे शून्य पर सेट होने से रोका जा सकता है):

private String name = "";

उदाहरण के लिए, printया तो printStringविधि शून्य के लिए जाँच कर सकती है :

printString((name == null) ? "" : name);

या आप वर्ग को डिजाइन कर सकते हैं ताकि name हमेशा एक अशक्त मान हो :

public class Printer {
    private final String name;

    public Printer(String name) {
        this.name = Objects.requireNonNull(name);
    }

    public void print() {
        printString(name);
    }

    private void printString(String s) {
        System.out.println(s + " (" + s.length() + ")");
    }

    public static void main(String[] args) {
        Printer printer = new Printer("123");
        printer.print();
    }
}

यह सभी देखें:

मुझे अभी भी समस्या नहीं मिल रही है

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


44
+1 अच्छा उदाहरण है जिसमें स्टैकट्रेस से गुजरना शामिल है; यह दिखाना महत्वपूर्ण है कि एनपीई को डीबग करना क्यों महत्वपूर्ण है। (और क्यों हम लगभग हमेशा एक स्टैकट्रेस की तलाश करते हैं जब कोई व्यक्ति किसी त्रुटि के बारे में सवाल पोस्ट करता है)
डेनिस मेंग

16
आपने डिबगिंग का उल्लेख किया है ... यह कैसे काम करता है? मैं कुछ समय से इस विषय पर शोध कर रहा हूं, लेकिन कुछ भी नहीं पा रहा हूं। मुझे यकीन है कि आप एक अद्भुत शिक्षक की तरह इसे एक सेकंड में मुझे सिखा सकते हैं! बहुत बहुत धन्यवाद! :-)
रुचिर बरोनिया

15
@RuchirBaronia एक डीबगर आपको प्रोग्राम लाइन के माध्यम से लाइन में कदम रखने की अनुमति देता है यह देखने के लिए कि कौन से तरीके कहलाते हैं और कैसे चर बदले जाते हैं। आईडीई के पास ऐसा करने के लिए कुछ उपकरण होने चाहिए। उदाहरण के लिए vogella.com/tutorials/EclipseDebugging/article.html देखें ।
fgb

15
@RuchirBaronia आप किसी भी NullPointerException के आस-पास के तरीकों पर ब्रेकप्वाइंट सेट करते हैं जैसा कि स्टैकट्रेस में देखा गया है, और जो आप उनसे होने की उम्मीद करते हैं उसके खिलाफ चर के मूल्यों की जांच करें। यदि आप जानते हैं कि एक चर शून्य है जब यह नहीं होना चाहिए, तो आप मान बदलने वाले किसी भी कोड के आसपास ब्रेकपॉइंट सेट कर सकते हैं। वहाँ भी सशर्त ब्रेकप्वाइंट हैं जो आप उपयोग कर सकते हैं जो आपको बताएंगे कि कब मूल्य बदलता है।
fgb

6
स्ट्रिंग स्ट्रिंग को एक रिक्त स्ट्रिंग में सेट करना क्योंकि उनका डिफ़ॉल्ट मान एक खराब अभ्यास माना जाता है।
टाइनी

501

प्रश्न: क्या कारण हैं NullPointerException(NPE)?

आपको पता होना चाहिए के रूप में, जावा प्रकार में विभाजित हैं आदिम प्रकार ( boolean, intआदि) और संदर्भ प्रकार । जावा में संदर्भ प्रकार आपको विशेष मूल्य का उपयोग करने की अनुमति देते हैं nullजो "नो ऑब्जेक्ट" कहने का जावा तरीका है।

एक NullPointerExceptionजब भी अपने कार्यक्रम के प्रयास एक का उपयोग करने के क्रम में फेंक दिया जाता है nullजैसे कि यह एक वास्तविक संदर्भ था। उदाहरण के लिए, यदि आप इसे लिखते हैं:

public class Test {
    public static void main(String[] args) {
        String foo = null;
        int length = foo.length();   // HERE
    }
}

"HERE" लेबल वाला कथन length()एक nullसंदर्भ पर विधि को चलाने का प्रयास करने वाला है , और यह एक फेंक देगा NullPointerException

ऐसे कई तरीके हैं जो आप एक nullमूल्य का उपयोग कर सकते हैं जिसके परिणामस्वरूप एक होगा NullPointerException। वास्तव में, केवल चीजें जो आप बिना एनपीई के बिना कर सकते हैं nullवे हैं:

  • इसे एक रेफरेंस वेरिएबल में असाइन करें या रेफरेंस वेरिएबल से पढ़ें,
  • इसे एक ऐरे एलिमेंट पर असाइन करें या एरे एलीमेंट से पढ़ें (बशर्ते कि ऐरे रेफरेंस खुद नॉन-नेल हो!)।
  • इसे एक पैरामीटर के रूप में पास करें या परिणाम के रूप में वापस करें, या
  • ==या !=ऑपरेटरों, या का उपयोग कर यह परीक्षण instanceof

प्रश्न: मैं एनपीई स्टैकट्रेस कैसे पढ़ूं?

मान लीजिए कि मैं कार्यक्रम को संकलित करता हूं और ऊपर चलाता हूं:

$ javac Test.java 
$ java Test
Exception in thread "main" java.lang.NullPointerException
    at Test.main(Test.java:4)
$

पहला अवलोकन: संकलन सफल हुआ! कार्यक्रम में समस्या संकलन त्रुटि नहीं है। यह एक रनटाइम त्रुटि है। (कुछ आईडीई चेतावनी दे सकते हैं कि आपका कार्यक्रम हमेशा एक अपवाद फेंक देगा ... लेकिन मानक javacसंकलक नहीं करता है।)

दूसरा अवलोकन: जब मैं कार्यक्रम चलाता हूं, तो यह "gobbledy-gook" की दो पंक्तियों को आउटपुट करता है। गलत!! वह गुदगुदी-गोक नहीं है। यह एक स्टैकट्रेस है ... और यह महत्वपूर्ण जानकारी प्रदान करता है जो आपको अपने कोड में त्रुटि को ट्रैक करने में मदद करेगा यदि आप इसे ध्यान से पढ़ने के लिए समय लेते हैं।

तो आइए देखें कि यह क्या कहता है:

Exception in thread "main" java.lang.NullPointerException

स्टैक ट्रेस की पहली पंक्ति आपको कई चीजें बताती है:

  • यह आपको जावा थ्रेड का नाम बताता है जिसमें अपवाद फेंका गया था। एक धागे के साथ एक साधारण कार्यक्रम के लिए (जैसे यह एक), यह "मुख्य" होगा। पर चलते हैं ...
  • यह आपको उस अपवाद का पूरा नाम बताता है जिसे फेंका गया था; यानी java.lang.NullPointerException
  • यदि अपवाद में संबंधित त्रुटि संदेश है, तो वह अपवाद नाम के बाद आउटपुट होगा। NullPointerExceptionइस संबंध में असामान्य है, क्योंकि इसमें शायद ही कोई त्रुटि संदेश है।

एनपीई के निदान में दूसरी पंक्ति सबसे महत्वपूर्ण है।

at Test.main(Test.java:4)

यह हमें कई बातें बताता है:

  • "एट टेस्ट.मेन" कहता है कि हम कक्षा की mainविधि में थे Test
  • "Test.java:4" कक्षा का स्रोत फ़ाइल नाम देता है, और यह हमें बताता है कि यह कथन जहां हुआ है वह फ़ाइल की पंक्ति 4 में है।

यदि आप ऊपर फ़ाइल में लाइनें गिनते हैं, तो पंक्ति 4 वह है जिसे मैंने "यहां" टिप्पणी के साथ लेबल किया है।

ध्यान दें कि अधिक जटिल उदाहरण में, एनपीई स्टैक ट्रेस में बहुत सारी लाइनें होंगी। लेकिन आप यह सुनिश्चित कर सकते हैं कि दूसरी पंक्ति (पहली "एट" लाइन) आपको बताएगी कि एनपीई 1 कहां फेंका गया था ।

संक्षेप में, स्टैक ट्रेस हमें स्पष्ट रूप से बताएगा कि कार्यक्रम के किस कथन ने एनपीई को फेंक दिया है।

1 - बिल्कुल सच नहीं है। नेस्टेड अपवाद नामक चीजें हैं ...

प्रश्न: मैं अपने कोड में NPE अपवाद के कारण को कैसे ट्रैक करूं?

यह कठिन भाग है। संक्षिप्त उत्तर स्टैक ट्रेस, स्रोत कोड और प्रासंगिक API दस्तावेज़ीकरण द्वारा प्रदान किए गए साक्ष्य के तार्किक तर्क को लागू करना है।

आइए पहले सरल उदाहरण (ऊपर) से स्पष्ट करें। हम उस रेखा को देखकर शुरू करते हैं जो स्टैक ट्रेस ने हमें बताया है कि एनपीई कहां हुआ है:

int length = foo.length(); // HERE

कैसे एक NPE फेंक सकते हैं?

वास्तव में, केवल एक ही तरीका है: यह केवल तभी हो सकता fooहै जब मूल्य हो null। हम तो length()विधि को चलाने की कोशिश करते हैं nullऔर ... बैंग!

लेकिन (मैं आपको कहता सुनता हूं) क्या होगा अगर एनपीई को length()विधि कॉल के अंदर फेंक दिया गया था ?

ठीक है, अगर ऐसा हुआ, तो स्टैक ट्रेस अलग दिखाई देगा। पहली "एट" लाइन कहेगी कि अपवाद को java.lang.Stringक्लास में किसी लाइन में फेंक दिया गया था और 4 की लाइन Test.javaदूसरी "लाइन" पर होगी।

तो यह कहां nullसे आया? इस मामले में, यह स्पष्ट है, और यह स्पष्ट है कि इसे ठीक करने के लिए हमें क्या करने की आवश्यकता है। (एक गैर-शून्य मान असाइन करें foo।)

ठीक है, तो चलिए थोड़ा और मुश्किल उदाहरण पेश करते हैं। इसके लिए कुछ तार्किक कटौती की आवश्यकता होगी ।

public class Test {

    private static String[] foo = new String[2];

    private static int test(String[] bar, int pos) {
        return bar[pos].length();
    }

    public static void main(String[] args) {
        int length = test(foo, 1);
    }
}

$ javac Test.java 
$ java Test
Exception in thread "main" java.lang.NullPointerException
    at Test.test(Test.java:6)
    at Test.main(Test.java:10)
$ 

तो अब हमारे पास दो "एट" लाइनें हैं। इस लाइन के लिए पहला है:

return args[pos].length();

और दूसरा इस लाइन के लिए है:

int length = test(foo, 1);

पहली पंक्ति को देखते हुए, यह एक NPE कैसे फेंक सकता है? इसके दो तरीके हैं:

  • यदि का मान barहै nullतो bar[pos]एक NPE फेंक देंगे।
  • यदि का मान है bar[pos], nullतो उस length()पर कॉल करने से एनपीई फेंक देगा।

इसके बाद, हमें यह पता लगाने की जरूरत है कि वास्तव में क्या हो रहा है। हम पहले वाले की खोज शुरू करेंगे:

कहाँ barसे आता है? यह testमेथड कॉल का एक पैरामीटर है , और अगर हम testदेखें कि कैसे बुलाया जाता है, तो हम देख सकते हैं कि यह fooस्टैटिक वेरिएबल से आता है । इसके अलावा, हम स्पष्ट रूप से देख सकते हैं कि हमने fooगैर-शून्य मान के लिए इनिशियलाइज़ किया है। जो इस स्पष्टीकरण को अस्थायी रूप से खारिज करने के लिए पर्याप्त है। (सिद्धांत में, कुछ और बदल सकता fooहै null... लेकिन यहां ऐसा नहीं हो रहा है।)

तो हमारे दूसरे परिदृश्य के बारे में क्या? ठीक है, हम देख सकते हैं कि posहै 1, तो इसका मतलब है कि foo[1]होना चाहिए null। क्या यह संभव है?

वास्तव में यह है! और यही समस्या है। जब हम इस तरह की शुरुआत करते हैं:

private static String[] foo = new String[2];

हम ऐसे String[]दो तत्वों के साथ आवंटित करते हैं, जिन्हें आरंभिक किया जाता हैnull । उसके बाद, हमने foo... की सामग्री को नहीं बदला foo[1]है null


425

यह ऐसा है जैसे आप किसी वस्तु तक पहुंचने का प्रयास कर रहे हैं null। नीचे दिए गए उदाहरण पर विचार करें:

TypeA objA;

इस समय आपने केवल इस ऑब्जेक्ट को घोषित किया है, लेकिन आरंभिक या त्वरित नहीं । और जब भी आप इसमें किसी संपत्ति या विधि का उपयोग करने का प्रयास करेंगे, तो यह फेंक देगा NullPointerExceptionजो समझ में आता है।

इस नीचे दिए गए उदाहरण को देखें:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown

1
अगर हम System.out.println (a.length ()) देते हैं; // NullPointerException को फेंक दिया जाएगा, इसे छोड़ने के लिए हम try catch block से हैंडल कर सकते हैं। धन्यवाद
विजया वर्मा Lanke

359

एक नल पॉइंटर अपवाद तब फेंका जाता है जब कोई एप्लिकेशन किसी ऐसे मामले में नल का उपयोग करने का प्रयास करता है जहां एक वस्तु की आवश्यकता होती है। इसमें शामिल है:

  1. किसी nullवस्तु की आवृत्ति विधि को कॉल करना ।
  2. किसी nullवस्तु के क्षेत्र में पहुँच या संशोधन ।
  3. लंबाई लेते हुए nullमानो यह एक सरणी हो।
  4. एक्सेस करना या स्लॉट्स को संशोधित करना nullजैसे कि यह एक ऐरे था।
  5. फेंकना nullमानो फेंकने योग्य मूल्य हो।

nullऑब्जेक्ट के अन्य अवैध उपयोगों को इंगित करने के लिए अनुप्रयोगों को इस वर्ग के उदाहरणों को फेंकना चाहिए ।

संदर्भ: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html


12
इसे सरल रखें, मुझे यह उत्तर पसंद है, इसे जोड़ें यदि आप सही मानते हैं - किसी वस्तु की अनैतिक रूप से विशेषता तक पहुंच
एमिलियानो

5
@ ईमिलियानो - बस एक प्रारंभिक विशेषता तक पहुँचने के लिए एक NPE का कारण नहीं है। यह वह है जो आप करते हैं >> असम्बद्ध विशेषता मान के साथ जो एनपीई का कारण बनता है।
स्टीफन सी

1
यदि आप अधिक मामले चाहते हैं: 1) nullएक synchronizedब्लॉक के लक्ष्य के रूप में , 2) का उपयोग कर के nullरूप में switch, और अनबॉक्सिंग के लक्ष्य के रूप में null
स्टीफन सी

333

एक nullसूचक वह है जो कहीं नहीं इंगित करता है। जब आप एक पॉइंटर को रोकते हैं p, तो आप कहते हैं "मुझे" पी "में संग्रहीत स्थान पर डेटा दें। जब pएक nullपॉइंटर है, तो इसमें संग्रहीत स्थान pहै nowhere, आप कह रहे हैं" मुझे स्थान 'कहीं' पर डेटा दें। " जाहिर है, यह ऐसा नहीं कर सकता है, इसलिए यह फेंकता है null pointer exception

सामान्य तौर पर, यह इसलिए है क्योंकि कुछ को ठीक से आरंभ नहीं किया गया है।


2
क्या हम एक डेटाबेस बना रहे हैं? -> जावा में NULLलिखा जाता nullहै। और यह एक संवेदनशील मामला है।
bvdb

3
"एक पूर्ण सूचक वह है जो कहीं नहीं इंगित करता है" मैं असहमत हूं। अशक्त बिंदु कहीं भी इंगित नहीं करते हैं, वे अशक्त मानों को इंगित करते हैं।
theRealChx101

2
@ TheRealChx101 एक शून्य सूचक और एक अशक्त मान के लिए एक संकेतक अलग चीजें हैं - एक शून्य सूचक एक शून्य मान को इंगित नहीं करता है। मान लीजिए कि आपके पास एक पॉइंटर को पॉइंटर है: पॉइंटर A पॉइंट टू पॉइंटर B और पॉइंटर B null है। इस स्थिति में, पॉइंटर A एक शून्य मान पर इंगित करता है, और पॉइंटर B एक अशक्त सूचक है।
श्रीजैब्रा

321

यह समझाने के लिए कि यह कैसे होता है और इसे कैसे ठीक किया जाए, बहुत सारे स्पष्टीकरण पहले से मौजूद हैं, लेकिन आपको इन सबसे बचने के लिए सर्वोत्तम प्रथाओं का भी पालन करना चाहिए NullPointerException

यह भी देखें: सर्वोत्तम प्रथाओं की एक अच्छी सूची

मैं जोड़ूंगा, बहुत महत्वपूर्ण है, finalसंशोधक का अच्छा उपयोग करें । जावा में लागू होने पर "अंतिम" संशोधक का उपयोग करना

सारांश:

  1. finalअच्छी आरंभीकरण लागू करने के लिए संशोधक का उपयोग करें ।
  2. तरीकों में अशक्त लौटने से बचें, उदाहरण के लिए जब लागू हो तो खाली संग्रह लौटाएं।
  3. एनोटेशन @NotNullऔर का उपयोग करें@Nullable
  4. जब वे शून्य नहीं होना चाहिए, तो पूरे अनुप्रयोग के माध्यम से अशक्त वस्तुओं के प्रसार से बचने के लिए तेजी से उपयोग करें और जोर का उपयोग करें।
  5. पहले ज्ञात ऑब्जेक्ट के साथ बराबर का उपयोग करें: if("knownObject".equals(unknownObject)
  6. पसंद करते हैं valueOf()अधिक toString()
  7. अशक्त सुरक्षित StringUtilsतरीकों का उपयोग करें StringUtils.isEmpty(null)
  8. जावा 8 का उपयोग करें तरीकों में वापसी मूल्य के रूप में वैकल्पिक, वैकल्पिक वर्ग शून्य संदर्भों के बजाय वैकल्पिक मूल्यों का प्रतिनिधित्व करने के लिए एक समाधान प्रदान करता है।

4
J2ee प्रोजेक्ट्स में, Nullpointer अपवाद बहुत ही सामान्य है। कुछ मामलों में संदर्भ चर को शून्य मान मिला है। तो आपको चर आरंभीकरण को ठीक से जांचना चाहिए। और सशर्त विवरण के दौरान आपको हमेशा जांचना चाहिए कि ध्वज या संदर्भ में शून्य है या नहीं जैसे: यदि (झंडा! = 0) {ur code जो flag का उपयोग करता है}
अमरेश पट्टनायक

14
यह ध्यान देने योग्य है कि कुछ आईडीई (जैसे ग्रहण) अनुकूलन योग्य एनोटेशन (जैसे @Nullableऊपर सूचीबद्ध) के आधार पर स्वचालित अशक्त एनालिसिस की पेशकश करते हैं और संभावित त्रुटियों के बारे में चेतावनी देते हैं। मौजूदा कोड संरचना के आधार पर इस तरह के एनोटेशन का अनुमान लगाना और उत्पन्न करना संभव है (जैसे इंटेलीजे ऐसा कर सकते हैं)।
Jan Chimiak

4
पहली बात यह करनी चाहिए कि एक अशक्त वस्तु का उपयोग करने से पहले, आपको यह जांचना चाहिए कि क्या यह अशक्त है, का उपयोग कर रहा है if (obj==null)। यदि यह अशक्त है तो आपको उसे भी संभालने के लिए कोड लिखना चाहिए।
लकमल विथानागे

4
IMO, जब संभव हो तो अशक्त वस्तुओं को वापस करने से बचना बेहतर होता है और जब अनुबंध में parametersif (obj == null) amount की मात्रा को कम करने, अनुबंध द्वारा, शून्य इनपुट मापदंडों की अनुमति नहीं होती है, तो एनोटेशन का उपयोग करें। कोड पठनीयता।
एलजी

4
इसे पढ़ें ... इससे पहले कि आप इन "सर्वोत्तम प्रथाओं" को सत्य के रूप में स्वीकार करें: satisfice.com/blog/archives/27
स्टीफन सी

316

जावा में, सब कुछ (आदिम प्रकारों को छोड़कर) एक वर्ग के रूप में है।

यदि आप किसी वस्तु का उपयोग करना चाहते हैं तो आपके पास दो चरण हैं:

  1. प्रचार
  2. प्रारंभ

उदाहरण:

  • घोषणा: Object object;
  • प्रारंभ: object = new Object();

सरणी अवधारणा के लिए भी:

  • घोषणा: Item item[] = new Item[5];
  • प्रारंभ: item[0] = new Item();

यदि आप इनिशियलाइज़ेशन सेक्शन नहीं दे रहे हैं तो NullPointerExceptionउठें।


3
एक NullPointerException अक्सर आवृत्ति के कॉलिंग विधि के दौरान होती है। उदाहरण के लिए, यदि आप एक संदर्भ घोषित करते हैं, लेकिन यह किसी भी उदाहरण को इंगित नहीं करता है, तो NullPointerException तब होगी जब आप इसकी विधि को कॉल करते हैं। जैसे: YourClass Ref = null; // या रेफ = एक और रीफ; // लेकिन एक औरRef ने किसी भी उदाहरण को संदर्भित नहीं किया है। RefomeMethod (); // यह NullPointerException को फेंक देगा। आम तौर पर इसे इस तरह से ठीक करें: विधि को कॉल करने से पहले, यह निर्धारित करें कि क्या संदर्भ शून्य है। जैसे: if (yourRef! = null) {yourRef.someMethod (); }
सूर्यहंग

2
या अपवाद कैप्चर का उपयोग करें: जैसे: कोशिश {yourRef.someMethod (); } कैच (NullPointerException e) {// TODO}
sunhang


315

एक नल सूचक अपवाद एक संकेतक है जिसे आप किसी ऑब्जेक्ट का उपयोग कर रहे हैं इसे प्रारंभ किए बिना।

उदाहरण के लिए, नीचे एक छात्र वर्ग है जो हमारे कोड में इसका उपयोग करेगा।

public class Student {

    private int id;

    public int getId() {
        return this.id;
    }

    public setId(int newId) {
        this.id = newId;
    }
}

नीचे दिया गया कोड आपको एक शून्य सूचक अपवाद देता है।

public class School {

    Student student;

    public School() {
        try {
            student.getId();
        }
        catch(Exception e) {
            System.out.println("Null pointer exception");
        }
    }
}

क्योंकि आप उपयोग कर रहे हैं student, लेकिन आप इसे नीचे दिए गए सही कोड की तरह शुरू करना भूल गए:

public class School {

    Student student;

    public School() {
        try {
            student = new Student();
            student.setId(12);
            student.getId();
        }
        catch(Exception e) {
            System.out.println("Null pointer exception");
        }
    }
}

7
हालांकि यह एक अच्छा उदाहरण है, क्या मैं यह पूछ सकता हूं कि यह उस सवाल को जोड़ता है जो पहले से ही अन्य सभी उत्तरों से कवर नहीं है?
रहस्यमय

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

2
एनपीई एक संकेतक हो सकता है कि आप एक असिंचित क्षेत्र का उपयोग कर रहे हैं। यह एक संकेतक हो सकता है कि आप अन्य चीजें कर रहे हैं। इस तरह से किसी एक कारण को लागू करने से किसी को एनपीई समस्याओं को हल करने में मदद नहीं मिलती है ... यदि वास्तविक कारण यह नहीं है।
स्टीफन सी

309

में जावा सभी चर आप यह घोषणा वास्तव में खुद को वस्तुओं रहे हैं वस्तुओं (या पुरातन) करने के लिए "संदर्भ" और नहीं।

जब आप किसी ऑब्जेक्ट विधि को निष्पादित करने का प्रयास करते हैं, तो संदर्भ उस ऑब्जेक्ट को निष्पादित करने के लिए जीवित ऑब्जेक्ट से पूछता है। लेकिन अगर संदर्भ NULL (शून्य, शून्य, शून्य) का संदर्भ दे रहा है, तो कोई तरीका नहीं है जिससे विधि निष्पादित हो जाती है। तब रनटाइम आपको NullPointerException को फेंकने से यह पता चलता है।

आपका संदर्भ अशक्त करने के लिए "इंगित" कर रहा है, इस प्रकार "नल -> सूचक"।

ऑब्जेक्ट VM मेमोरी स्पेस में रहता है और इसे एक्सेस करने का एकमात्र तरीका thisसंदर्भों का उपयोग कर रहा है । इस उदाहरण को लें:

public class Some {
    private int id;
    public int getId(){
        return this.id;
    }
    public setId( int newId ) {
        this.id = newId;
    }
}

और अपने कोड में किसी अन्य स्थान पर:

Some reference = new Some();    // Point to a new object of type Some()
Some otherReference = null;     // Initiallly this points to NULL

reference.setId( 1 );           // Execute setId method, now private var id is 1

System.out.println( reference.getId() ); // Prints 1 to the console

otherReference = reference      // Now they both point to the only object.

reference = null;               // "reference" now point to null.

// But "otherReference" still point to the "real" object so this print 1 too...
System.out.println( otherReference.getId() );

// Guess what will happen
System.out.println( reference.getId() ); // :S Throws NullPointerException because "reference" is pointing to NULL remember...

यह जानने के लिए एक महत्वपूर्ण बात है - जब किसी वस्तु के संदर्भ नहीं होते हैं (ऊपर के उदाहरण में जब referenceऔर जब otherReferenceदोनों को इंगित करते हैं) तब ऑब्जेक्ट "अगम्य" होता है। हमारे पास इसके साथ काम करने का कोई तरीका नहीं है, इसलिए यह ऑब्जेक्ट कचरा एकत्र करने के लिए तैयार है, और कुछ बिंदु पर, वीएम इस ऑब्जेक्ट द्वारा उपयोग की जाने वाली मेमोरी को मुक्त कर देगा और दूसरे को आवंटित करेगा।


280

एक और घटना NullPointerExceptionतब घटित होती है जब कोई वस्तु सरणी घोषित करता है, तो तुरंत उसके अंदर तत्वों को हटाने की कोशिश करता है।

String[] phrases = new String[10];
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

यदि तुलना क्रम को उलट दिया जाता है तो इस विशेष NPE से बचा जा सकता है; अर्थात्, .equalsगारंटीकृत गैर-शून्य ऑब्जेक्ट पर उपयोग करें ।

एक सरणी के अंदर सभी तत्वों को उनके सामान्य प्रारंभिक मूल्य के लिए आरंभीकृत किया जाता है ; किसी भी प्रकार के ऑब्जेक्ट ऐरे के लिए, इसका मतलब है कि सभी तत्व हैं null

आपको ऐक्सेस या डीफ़रेंसिंग करने से पहले एरे में तत्वों को इनिशियलाइज़ करना होगा

String[] phrases = new String[] {"The bird", "A bird", "My bird", "Bird"};
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

इंस्टेंस लेवल (क्लास लेवल नहीं) पर अनइंस्टॉल किए गए ऑब्जेक्ट पर ऑपरेशन NullPointerException को लीड करेगा। उदाहरण के लिए ऑपरेशन की आवश्यकता है। यदि ऑपरेशन क्लास लेवल पर है, तो यह कहा जाता है कि अनैतिक तरीके से ऑब्जेक्ट पर स्टैटिक मेथड है तो यह NullPointerException अपवाद को नहीं फेंकेगा। यहां तक ​​कि आदिम आवरण श्रेणी की वस्तुएं NullPointerException को फेंकती हैं।
शैलेंद्र सिंह

1. NullPointerException एक RuntimeException है, इसका मतलब है कि जब आपका प्रोग्राम चल रहा होगा, तो आप संकलन समय पर नहीं आएंगे! :(, लेकिन अधिकांश IDE आपको इसे खोजने में मदद करते हैं। 2. असाइनमेंट स्टेटमेंट में कीवर्ड 'null' के उपयोग को कम करें। :) संदर्भ url:
tomj0101

@ tomj0101 मैं पूरी तरह से स्पष्ट नहीं हूं कि आपने यह टिप्पणी क्यों की ... लेकिन आपके दूसरे बिंदु पर, इससे पहले कि एक पैटर्न Optionalअशक्त था। कीवर्ड ठीक है। यह जानना कि इसके खिलाफ चौकसी कैसी है। यह इसकी एक सामान्य घटना और इसे कम करने के तरीके प्रदान करता है।
मकोतो

NullPointerException एक रन-टाइम अपवाद है जिसे इसे पकड़ने की अनुशंसा नहीं की जाती है, लेकिन इसके बजाय इसे से बचें।
शोमू

2
@ शोमू: मैं किस बिंदु पर भी सुझाव देता हूं कि इसे पकड़ा जाना चाहिए?
मकोतो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.