什么是 Null Pointer Exceptions ( java.lang.NullPointerException) 以及導(dǎo)致它們的原因是什么?
可以使用哪些方法/工具來(lái)確定原因,以便您阻止異常導(dǎo)致程序過(guò)早終止?
文章來(lái)源地址http://www.zghlxwxcb.cn/article/261.html
Java 中有兩種主要類(lèi)型的變量:
原語(yǔ):包含數(shù)據(jù)的變量。如果您想操作原始變量中的數(shù)據(jù),您可以直接操作該變量。按照慣例,基本類(lèi)型以小寫(xiě)字母開(kāi)頭。例如類(lèi)型變量int or char是原語(yǔ)。
References:包含 an 的內(nèi)存地址的變量,Object 即引用 Object. 如果你想操作 Object 引用變量引用的對(duì)象,你必須取消引用它。取消引用通常需要使用.來(lái)訪(fǎng)問(wèn)方法或字段,或者使用 [ 來(lái)索引數(shù)組。按照慣例,引用類(lèi)型通常用以大寫(xiě)字母開(kāi)頭的類(lèi)型表示。例如,類(lèi)型變量 Object 是引用。
考慮以下代碼,您在其中聲明了一個(gè)原始類(lèi)型的變量 int 并且不對(duì)其進(jìn)行初始化:
int x;int y = x + x;
這兩行會(huì)使程序崩潰,因?yàn)闆](méi)有指定值
這兩行會(huì)使程序崩潰,因?yàn)闆](méi)有指定值 x ,而我們正試圖使用 x 的值來(lái)指定 y。所有原語(yǔ)在被操作之前都必須被初始化為一個(gè)可用的值。
現(xiàn)在事情變得有趣了。引用變量可以設(shè)置為 null“我沒(méi)有引用任何東西”。null如果您以這種方式顯式設(shè)置引用變量,或者引用變量未初始化且編譯器未捕獲它(Java 會(huì)自動(dòng)將變量設(shè)置為null),則可以獲得引用變量中的值。
如果引用變量由您顯式設(shè)置或通過(guò) Java 自動(dòng)設(shè)置為 null,并且您嘗試取消引用它,您會(huì)得到一個(gè)NullPointerException.
( NullPointerExceptionNPE) 通常發(fā)生在聲明變量但未創(chuàng)建對(duì)象并將其分配給變量時(shí),然后再?lài)L試使用變量的內(nèi)容。所以你引用了一些實(shí)際上不存在的東西。
采取以下代碼:
Integer num; num = new Integer(10);
第一行聲明了一個(gè)名為 的變量num,但它實(shí)際上還沒(méi)有包含一個(gè)引用值。由于您尚未說(shuō)明要指向什么,因此 Java 將其設(shè)置為null.
在第二行中,new關(guān)鍵字用于實(shí)例化(或創(chuàng)建)類(lèi)型的對(duì)象Integer,并將引用變量num分配給該Integer對(duì)象。
如果您在創(chuàng)建對(duì)象num 之前嘗試取消引用,您會(huì)得到一個(gè)NullPointerException. 在最普通的情況下,編譯器會(huì)發(fā)現(xiàn)問(wèn)題并讓您知道“ num may not have been initialized,”,但有時(shí)您可能會(huì)編寫(xiě)不直接創(chuàng)建對(duì)象的代碼。
例如,您可能有如下方法:
public void doSomething(SomeObject obj) { // Do something to obj, assumes obj is not null obj.myMethod();}
在這種情況下,您不是在創(chuàng)建對(duì)象obj,而是假設(shè)它是在doSomething()調(diào)用方法之前創(chuàng)建的。注意,可以這樣調(diào)用方法:
doSomething(null);
在這種情況下,
在這種情況下,obj是null,語(yǔ)句obj.myMethod()將拋出一個(gè)NullPointerException。
如果該方法打算像上述方法一樣對(duì)傳入的對(duì)象執(zhí)行某些操作,則拋出是合適的,NullPointerException因?yàn)檫@是程序員錯(cuò)誤,程序員將需要該信息進(jìn)行調(diào)試。
// Throws an NPE with a custom error message if obj is null Objects.requireNonNull(obj, "obj must not be null");
除了作為NullPointerException方法邏輯結(jié)果拋出的 s 之外,您還可以檢查方法參數(shù)的null值并通過(guò)在方法開(kāi)頭附近添加如下內(nèi)容來(lái)顯式拋出 NPE:
請(qǐng)注意,在您的錯(cuò)誤消息中清楚說(shuō)明哪個(gè)對(duì)象不能是很有幫助的null。驗(yàn)證這一點(diǎn)的好處是 1) 您可以返回自己更清晰的錯(cuò)誤消息,以及 2) 對(duì)于您知道的方法的其余部分,除非obj重新分配,否則它不為 null 并且可以安全地取消引用。
或者,在某些情況下,該方法的目的不僅僅是對(duì)傳入的對(duì)象進(jìn)行操作,因此 null 參數(shù)可能是可以接受的。在這種情況下,您需要檢查空參數(shù)并采取不同的行為。您還應(yīng)該在文檔中解釋這一點(diǎn)。例如,doSomething()可以寫(xiě)成:
/** * @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 }}
【可以使用哪些方法/工具來(lái)確定原因,以便您阻止異常導(dǎo)致程序過(guò)早終止?】
帶有 find bugs 的 Sonar 可以檢測(cè) NPE。 sonar能否動(dòng)態(tài)捕獲JVM引起的空指針異常
現(xiàn)在 Java 14 添加了一個(gè)新的語(yǔ)言特性來(lái)顯示 NullPointerException 的根本原因。自 2006 年以來(lái),此語(yǔ)言功能已成為 SAP 商業(yè) JVM 的一部分。
在 Java 14 中,以下是 NullPointerException 異常消息的示例:
【在線(xiàn)程“main”中 java.lang.NullPointerException:無(wú)法調(diào)用“java.util.List.size()”,因?yàn)椤發(fā)ist”為空】
NullPointerException導(dǎo)致 a發(fā)生的情況列表
NullPointerException
以下是Java 語(yǔ)言規(guī)范直接*提到的所有發(fā)生 a 的情況:
訪(fǎng)問(wèn)(即獲取或設(shè)置)空引用的實(shí)例字段。(靜態(tài)字段不算數(shù)!)
調(diào)用空引用的實(shí)例方法。(靜態(tài)方法不算!)
throw null;
訪(fǎng)問(wèn)空數(shù)組的元素。
同步空 -
synchronized (someNullReference) { ... }
NullPointerException
如果其操作數(shù)之一是裝箱的空引用,則任何整數(shù)/浮點(diǎn)運(yùn)算符都可以?huà)伋?aNullPointerException
如果裝箱值為 null,則取消裝箱轉(zhuǎn)換將拋出 a 。調(diào)用
super
空引用會(huì)拋出一個(gè)NullPointerException
. 如果您感到困惑,這是在談?wù)摵细竦某?lèi)構(gòu)造函數(shù)調(diào)用:
class Outer { class Inner {}}class ChildOfInner extends Outer.Inner { ChildOfInner(Outer o) { o.super(); // if o is null, NPE gets thrown }}
使用
for (element : iterable)
循環(huán)遍歷空集合/數(shù)組。switch (foo) { ... }
(無(wú)論是表達(dá)式還是語(yǔ)句)可以?huà)伋鲆粋€(gè)NullPointerException
whenfoo
is null。foo.new SomeInnerClass()
NullPointerException
當(dāng)為空時(shí)拋出一個(gè)foo
。形式的方法引用
name1::name2
orprimaryExpression::name
throws aNullPointerException
when evaluated whenname1
orprimaryExpression
evaluates to null.JLS here 的一條注釋說(shuō),
someInstance.someStaticMethod()
不會(huì)拋出 NPE,因?yàn)樗?/span>someStaticMethod
是靜態(tài)的,但someInstance::someStaticMethod
仍然會(huì)拋出 NPE!文章來(lái)源:http://www.zghlxwxcb.cn/article/261.html
到此這篇關(guān)于什么是 NullPointerException,我該如何修復(fù)它?的文章就介紹到這了,更多相關(guān)內(nèi)容可以在右上角搜索或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!