NullPointerException क्या है, और मैं इसे कैसे ठीक करूँ?
अशक्त सूचक अपवाद ( java.lang.NullPointerException
) क्या हैं और उनके कारण क्या हैं?
कारण निर्धारित करने के लिए किन तरीकों / साधनों का उपयोग किया जा सकता है ताकि आप कार्यक्रम को समय से पहले समाप्त करने से अपवाद को रोक सकें?
जवाब
जब आप एक संदर्भ चर (यानी एक वस्तु) की घोषणा करते हैं तो आप वास्तव में एक ऑब्जेक्ट के लिए एक पॉइंटर बना रहे हैं। निम्नलिखित कोड पर विचार करें जहां आप आदिम प्रकार का एक चर घोषित करते हैं 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, assumes obj is not null
obj.myMethod();
}
किस मामले में, आप ऑब्जेक्ट नहीं बना रहे हैं obj
, बल्कि यह मानकर कि इसे doSomething()
विधि कहा जाने से पहले बनाया गया था। ध्यान दें, इस तरह से विधि को कॉल करना संभव है:
doSomething(null);
जो मामले में, obj
है null
, और बयान obj.myMethod()
एक फेंक देगा NullPointerException
।
यदि विधि का उद्देश्य उपरोक्त विधि के अनुसार पारित वस्तु के लिए कुछ करना है, तो इसे फेंकना उचित है NullPointerException
क्योंकि यह एक प्रोग्रामर त्रुटि है और प्रोग्रामर को डिबगिंग उद्देश्यों के लिए उस जानकारी की आवश्यकता होगी।
NullPointerException
विधि के तर्क के परिणामस्वरूप फेंके गए एस के अलावा , आप null
मानों के लिए विधि तर्कों की भी जांच कर सकते हैं और NPEs को स्पष्ट रूप से किसी विधि की शुरुआत के पास निम्नलिखित की तरह जोड़कर फेंक सकते हैं:
//Throws an NPE with a custom error message if obj is null
Objects.requireNonNull(obj, "obj must not be null");
ध्यान दें कि यह आपके त्रुटि संदेश में स्पष्ट रूप से कहने में सहायक है कि कौन सी वस्तु नहीं हो सकती है null
। इस तरह से सत्यापन करने का लाभ यह है कि 1) आप अपने स्वयं के क्लियर एरर मैसेज और 2) वापस कर सकते हैं, बाकी की विधि के बारे में आप जानते हैं कि जब तक obj
पुन: असाइन नहीं किया जाता है, तब तक यह अशक्त नहीं है और इसे सुरक्षित रूप से डीरेल किया जा सकता है।
वैकल्पिक रूप से, ऐसे मामले हो सकते हैं जहां विधि का उद्देश्य केवल ऑब्जेक्ट में पारित होने पर काम करना नहीं है, और इसलिए एक शून्य पैरामीटर स्वीकार्य हो सकता है। इस मामले में, आपको एक अशक्त पैरामीटर की जांच करने और अलग तरह से व्यवहार करने की आवश्यकता होगी । आपको यह भी प्रलेखन में स्पष्ट करना चाहिए। उदाहरण के लिए, के 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
}
}
अंत में, स्टैक ट्रेस का उपयोग करके अपवाद और कारण को कैसे इंगित करें
कारण निर्धारित करने के लिए किन तरीकों / साधनों का उपयोग किया जा सकता है ताकि आप कार्यक्रम को समय से पहले समाप्त करने से अपवाद को रोक सकें?
सोनार कीड़े खोजने के साथ NPE का पता लगा सकता है। क्या सोनार JVM के कारण शून्य सूचक अपवादों को पकड़ सकता है
अब NullPointerException का मूल कारण दिखाने के लिए Java 14 ने एक नई भाषा सुविधा जोड़ी है। यह भाषा सुविधा 2006 से SAP वाणिज्यिक JVM का हिस्सा रही है। इस अद्भुत भाषा सुविधा को समझने के लिए निम्नलिखित 2 मिनट का समय दिया गया है।
https://jfeatures.com/blog/NullPointerException
जावा 14 में निम्नलिखित नमूना NullPointerException अपवाद संदेश है:
धागे में "मुख्य" java.lang.NullPointerException: "java.util.List.size ()" को लागू नहीं किया जा सकता क्योंकि "सूची" शून्य है
NullPointerException
s अपवाद हैं जो तब होते हैं जब आप एक संदर्भ का उपयोग करने का प्रयास करते हैं जो स्मृति (शून्य) में कोई स्थान नहीं बताता है, हालांकि यह एक ऑब्जेक्ट को संदर्भित कर रहा था। अशक्त संदर्भ पर एक विधि को कॉल करना या अशक्त संदर्भ के क्षेत्र तक पहुँचने की कोशिश करना एक ट्रिगर होगा NullPointerException
। ये सबसे आम हैं, लेकिन अन्य तरीके NullPointerExceptionjavadoc पेज पर सूचीबद्ध हैं ।
संभवतया सबसे तेज उदाहरण कोड मैं बता सकता हूं कि NullPointerException
यह होगा:
public class Example {
public static void main(String[] args) {
Object obj = null;
obj.hashCode();
}
}
पहली पंक्ति के अंदर main
, मैं स्पष्ट रूप से इसके बराबर Object
संदर्भ सेट कर रहा हूं । इसका मतलब है कि मेरे पास एक संदर्भ है, लेकिन यह किसी भी वस्तु की ओर इशारा नहीं कर रहा है। उसके बाद, मैं संदर्भ का इलाज करने की कोशिश करता हूं, हालांकि यह उस पर एक विधि को कॉल करके किसी ऑब्जेक्ट को इंगित करता है। इसका परिणाम यह होता है कि उस स्थान पर निष्पादित करने के लिए कोई कोड नहीं है जो संदर्भ इंगित कर रहा है।obj
null
NullPointerException
(यह एक तकनीकीता है, लेकिन मुझे लगता है कि यह उल्लेख करता है: एक संदर्भ जो अशक्त करने के लिए इंगित करता है, एक सी सूचक के समान नहीं है जो एक अमान्य मेमोरी स्थान को इंगित करता है। एक शून्य सूचक का शाब्दिक अर्थ कहीं भी इंगित नहीं है , जो सूक्ष्म रूप से भिन्न है। उस स्थान की ओर इशारा करना जो अमान्य होता है।)
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 देखें )।
प्रश्न: क्या कारण हैं 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 अपवाद के कारण को कैसे ट्रैक करूं?
यह कठिन भाग है। संक्षिप्त उत्तर स्टैक ट्रेस, स्रोत कोड और प्रासंगिक एपीआई प्रलेखन द्वारा प्रदान किए गए साक्ष्य के तार्किक तर्क को लागू करना है।
आइए पहले सरल उदाहरण (ऊपर) से स्पष्ट करें। हम उस रेखा को देखकर शुरू करते हैं जो स्टैक ट्रेस ने हमें बताया है कि एनपीई कहां हुआ है:
int length = foo.length(); // HERE
वह एनपीई कैसे फेंक सकता है?
वास्तव में, केवल एक ही तरीका है: यह केवल तभी हो सकता 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
।
यह ऐसा है जैसे आप किसी वस्तु तक पहुँचने का प्रयास कर रहे हैं null
। नीचे दिए गए उदाहरण पर विचार करें:
TypeA objA;
इस समय आपने केवल इस ऑब्जेक्ट को घोषित किया है लेकिन आरंभीकृत या त्वरित नहीं । और जब भी आप इसमें किसी संपत्ति या विधि का उपयोग करने का प्रयास करते हैं, तो यह फेंक देगा NullPointerException
जो समझ में आता है।
इस नीचे दिए गए उदाहरण को देखें:
String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
एक नल पॉइंटर अपवाद तब फेंका जाता है जब कोई एप्लिकेशन किसी ऐसे मामले में नल का उपयोग करने का प्रयास करता है जहां एक वस्तु की आवश्यकता होती है। इसमे शामिल है:
- किसी
null
वस्तु की आवृत्ति विधि को कॉल करना । - किसी
null
वस्तु के क्षेत्र में पहुँच या संशोधन । - लंबाई लेते हुए
null
मानो यह एक सरणी हो। null
किसी सरणी के रूप में स्लॉट्स को एक्सेस करना या संशोधित करना ।- फेंकना
null
मानो फेंकने योग्य मूल्य हो।
null
ऑब्जेक्ट के अन्य अवैध उपयोगों को इंगित करने के लिए अनुप्रयोगों को इस वर्ग के उदाहरणों को फेंकना चाहिए ।
संदर्भ: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html
एक null
सूचक वह है जो कहीं नहीं इंगित करता है। जब आप एक पॉइंटर को रोकते हैं p
, तो आप कहते हैं "मुझे" पी "में संग्रहीत स्थान पर डेटा दें। जब p
एक null
पॉइंटर है, तो इसमें संग्रहीत स्थान p
है nowhere
, आप कह रहे हैं" मुझे स्थान 'कहीं' पर डेटा दें। " जाहिर है, यह ऐसा नहीं कर सकता, इसलिए यह फेंकता है null pointer exception
।
सामान्य तौर पर, यह इसलिए है क्योंकि किसी चीज़ को ठीक से शुरू नहीं किया गया है।
यह समझाने के लिए कि यह कैसे होता है और इसे कैसे ठीक किया जाए, बहुत सारे स्पष्टीकरण पहले से मौजूद हैं, लेकिन आपको इन सबसे बचने के लिए सर्वोत्तम प्रथाओं का भी पालन करना चाहिए NullPointerException।
यह भी देखें: सर्वोत्तम प्रथाओं की एक अच्छी सूची
मैं जोड़ूंगा, बहुत महत्वपूर्ण है, final
संशोधक का अच्छा उपयोग करें । जावा में लागू होने पर "अंतिम" संशोधक का उपयोग करना
सारांश:
final
अच्छी आरंभीकरण लागू करने के लिए संशोधक का उपयोग करें ।- तरीकों में अशक्त लौटने से बचें, उदाहरण के लिए जब लागू हो तो खाली संग्रह लौटाएं।
- एनोटेशन @NotNullऔर का उपयोग करें@Nullable
- जब वे अशक्त नहीं होना चाहिए, तो पूरे अनुप्रयोग के माध्यम से अशक्त वस्तुओं के प्रसार से बचने के लिए तेजी से विफल और मुखर का उपयोग करें।
- पहले ज्ञात वस्तु के बराबर का उपयोग करें:
if("knownObject".equals(unknownObject)
- पसंद करते हैं
valueOf()
अधिकtoString()
। - अशक्त सुरक्षित StringUtilsतरीकों का उपयोग करें
StringUtils.isEmpty(null)
। - जावा 8 का उपयोग करें तरीकों में वापसी मूल्य के रूप में वैकल्पिक, वैकल्पिक वर्ग शून्य संदर्भों के बजाय वैकल्पिक मूल्यों का प्रतिनिधित्व करने के लिए एक समाधान प्रदान करता है।
जावा में, सब कुछ (आदिम प्रकारों को छोड़कर) एक वर्ग के रूप में है।
यदि आप किसी वस्तु का उपयोग करना चाहते हैं तो आपके पास दो चरण हैं:
- प्रचार
- प्रारंभ
उदाहरण:
- घोषणा:
Object object;
- आरंभ:
object = new Object();
सरणी अवधारणा के लिए भी:
- घोषणा:
Item item[] = new Item[5];
- आरंभ:
item[0] = new Item();
यदि आप इनिशियलाइज़ेशन सेक्शन नहीं दे रहे हैं तो NullPointerException
उठें।
एक अशक्त सूचक अपवाद एक संकेतक है जिसे आप किसी ऑब्जेक्ट का उपयोग किए बिना इसे प्रारंभ कर रहे हैं।
उदाहरण के लिए, नीचे एक छात्र वर्ग है जो हमारे कोड में इसका उपयोग करेगा।
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");
}
}
}
में जावा सभी चर आप यह घोषणा वास्तव में खुद को वस्तुओं रहे हैं वस्तुओं (या पुरातन) करने के लिए "संदर्भ" और नहीं।
जब आप किसी ऑब्जेक्ट विधि को निष्पादित करने का प्रयास करते हैं, तो संदर्भ उस ऑब्जेक्ट को निष्पादित करने के लिए जीवित ऑब्जेक्ट से पूछता है। लेकिन अगर संदर्भ 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
दोनों को इंगित करते हैं) तब ऑब्जेक्ट "अगम्य" होता है। हमारे पास इसके साथ काम करने का कोई तरीका नहीं है, इसलिए यह ऑब्जेक्ट कचरा एकत्र करने के लिए तैयार है, और कुछ बिंदु पर, वीएम इस ऑब्जेक्ट द्वारा उपयोग की जाने वाली मेमोरी को मुक्त कर देगा और दूसरे को आवंटित करेगा।
एक और घटना 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));
}