詳解Java中NullPointerException異常的原因詳解以及解決方法
NullPointerException是當(dāng)您嘗試使用指向內(nèi)存中空位置的引用(null)時(shí)發(fā)生的異常,就好像它引用了一個(gè)對(duì)象一樣。
當(dāng)我們聲明引用變量(即對(duì)象)時(shí),實(shí)際上是在創(chuàng)建指向?qū)ο蟮闹羔???紤]以下代碼,您可以在其中聲明基本類型的整型變量x:
int x; x = 10;
在此示例中,變量x是一個(gè)整型變量,Java將為您初始化為0。當(dāng)您在第二行中將其分配給10時(shí),值10將被寫入x指向的內(nèi)存中。
但是,當(dāng)您嘗試聲明引用類型時(shí)會(huì)發(fā)生不同的事情。請(qǐng)使用以下代碼:
Integer num; num = new Integer(10);
第一行聲明了一個(gè)名為的變量num,但它不包含原始值。相反,它包含一個(gè)指針(因?yàn)轭愋虸nteger是一個(gè)引用類型)。既然你還沒有說什么指向Java,它將它設(shè)置為null,意思是“ 我什么都沒有指向”。
在第二行中,new關(guān)鍵字用于實(shí)例化(或創(chuàng)建)Integer類型的對(duì)象,并為指針變量num分配此對(duì)象。您現(xiàn)在可以使用解引用運(yùn)算符.(點(diǎn))來(lái)引用對(duì)象。
在當(dāng)你聲明了一個(gè)變量,但是沒有創(chuàng)建一個(gè)對(duì)象,會(huì)發(fā)生Exception。如果您在創(chuàng)建num對(duì)象之前嘗試取消引用,則會(huì)得到一個(gè)NullPointerException。在最瑣碎的情況下,編譯器將捕獲問題并讓您知道“num可能尚未初始化”,但有時(shí)您編寫的代碼不會(huì)直接創(chuàng)建對(duì)象。
例如,您可能使用了如下的方法:
public void doSomething(SomeObject obj) {
//do something to obj
}
在這種情況下,您沒有創(chuàng)建對(duì)象obj,而是假設(shè)它是在doSomething調(diào)用方法之前創(chuàng)建的。如果你像這樣調(diào)用方法:
doSomething(null);
在這種情況下obj為null。如果該方法旨在對(duì)傳入的對(duì)象執(zhí)行某些操作,則需要拋出異常,因?yàn)镹ullPointerException它是程序錯(cuò)誤,程序員將需要該信息用于調(diào)試的目的。
或者,可能存在這樣的情況:該方法的目的不僅僅是對(duì)傳入的對(duì)象進(jìn)行操作,因此可以接受空參數(shù)。在這種情況下,您需要檢查null參數(shù)并采取不同的行為。您還應(yīng)該在文檔中解釋這一點(diǎn)。例如,doSomething應(yīng)該最好寫成:
/**
* @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
}
}
我如何解決它?
所以你有一個(gè)NullPointerException。應(yīng)該如何解決?讓我們舉一個(gè)簡(jiǎn)單的例子,它拋出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();
}
}
標(biāo)識(shí)空值
第一步是確切地確定導(dǎo)致異常的值。為此,我們需要做一些調(diào)試。學(xué)習(xí)閱讀堆棧跟蹤很重要。這將顯示拋出異常的位置:
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方法中)。查看該行并通過添加日志記錄語(yǔ)句或使用調(diào)試器來(lái)檢查哪些值為空。我們發(fā)現(xiàn)它s是null,并且調(diào)用length方法會(huì)拋出異常。我們可以看到程序在s.length()方法中刪除時(shí)停止拋出異常。
追蹤這些值來(lái)自哪里
接下來(lái)檢查此值的來(lái)源。按照該方法的調(diào)用者,我們可以看到,s與傳遞printString(name)的print()方法,并this.name為空。
跟蹤應(yīng)設(shè)置這些值的位置
在哪里this.name設(shè)置?在setName(String)方法中。通過一些更多的調(diào)試,我們可以看到根本沒有調(diào)用此方法。如果調(diào)用該方法,請(qǐng)確保檢查調(diào)用這些方法的順序,并且在print方法之后不調(diào)用set 方法。
這足以為我們提供一個(gè)解決方案:在調(diào)用printer.setName()之前添加調(diào)用printer.print()。
其他修正
該變量可以具有默認(rèn)值(并且setName可以防止將其設(shè)置為null):
private String name = "";
任一print或printString方法可以檢查空,例如:
printString((name == null) ? "" : name);
或者您可以設(shè)計(jì)如下所示的類,以便name 始終具有非null值:
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();
}
}
到此這篇關(guān)于詳解Java中NullPointerException異常的原因詳解以及解決方法的文章就介紹到這了,更多相關(guān)Java NullPointerException異常內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Java空指針異常NullPointerException的原因與解決方案
- 解決java.lang.NullPointerException問題(空指針異常)
- Java如何優(yōu)雅地避免空指針異常(NullPointerException)
- Java中redisTemplate注入失敗NullPointerException異常問題解決
- 詳解Java中NullPointerException異常的原因和解決辦法
- java.lang.NullPointerException異常問題解決方案
- java.lang.NullPointerException 如何處理空指針異常的實(shí)現(xiàn)
- Java中NullPointerException的異常解決
相關(guān)文章
選擇Spring Boot項(xiàng)目的內(nèi)嵌容器的理由
Spring Boot是由Pivotal團(tuán)隊(duì)提供的全新框架,其設(shè)計(jì)目的是用來(lái)簡(jiǎn)化新Spring應(yīng)用的初始搭建以及開發(fā)過程。這篇文章主要介紹了選擇Spring Boot項(xiàng)目的內(nèi)嵌容器,需要的朋友可以參考下2017-11-11
IntelliJ IDEA中如何構(gòu)建Spring Boot的項(xiàng)目
這篇文章主要介紹了IntelliJ IDEA中如何構(gòu)建Spring Boot的項(xiàng)目問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07
Spring Boot整合web層實(shí)現(xiàn)過程詳解
這篇文章主要介紹了Spring Boot整合web層實(shí)現(xiàn)過程詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04
JAVA中字符串函數(shù)subString的用法小結(jié)
本篇文章主要是對(duì)JAVA中字符串函數(shù)subString的用法進(jìn)行了詳細(xì)的介紹,需要的朋友可以過來(lái)參考下,希望對(duì)大家有所幫助2014-02-02
Java Stopwatch類,性能與時(shí)間計(jì)時(shí)器案例詳解
這篇文章主要介紹了Java Stopwatch類,性能與時(shí)間計(jì)時(shí)器案例詳解,本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-09-09
springboot單元測(cè)試兩種方法實(shí)例詳解
這篇文章主要介紹了springboot單元測(cè)試兩種方法實(shí)例詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12
鑒權(quán)認(rèn)證+aop+注解+過濾feign請(qǐng)求的實(shí)例
這篇文章主要介紹了鑒權(quán)認(rèn)證+aop+注解+過濾feign請(qǐng)求的實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03

