Java NullPointerException是未經檢查的異常,而且進行了擴展RuntimeException
。NullPointerException不會強制咱們使用catch塊來處理它。html
NullPointerException是代碼中您嘗試訪問/修改還沒有初始化的對象的狀況。從本質上講,它意味着對象引用變量沒有指向任何地方,而且不指向任何內容或爲「 null 」。一個拋出空指針異常的示例Java程序。java
package
com.howtodoinjava.demo.npe;
public
class
SampleNPE
{
public
static
void
main(String[] args)
{
String s =
null
;
System.out.println( s.toString() );
// 's' is un-initialized and is null
}
}
|
好吧,因爲各類緣由,NullPointerException可能會出如今代碼中的任何位置,可是我根據本身的經驗準備了最常出現的地點清單。express
null
toString()
對象的方法是null
if
不檢查null
相等性的狀況下比較塊中的對象屬性synchronized
在一個對象上使用null
這不是詳盡的清單。還有其餘幾個地方和緣由。若是您還能夠回憶起其餘任何內容,請發表評論。它也會幫助其餘人(初學者)。apache
若是不爲null,則此運算符將得出左側的值,不然將評估右側。它具備以下語法:api
布爾表達式?value1:value2;
若是expression計算爲true,則整個表達式將返回value1,不然返回value2。它更像if-else構造,可是更有效和更具表現力。爲了防止NullPointerException(NPE),請像如下代碼同樣使用此運算符:安全
字符串str =(參數==空)「 NA」:參數;
Apache commons lang是用於各類操做之王的幾個實用程序類的集合。其中之一是StringUtils.java。使用StringUtils.isNotEmpty()驗證做爲參數傳遞的字符串是否爲空或空字符串。若是不爲null或爲空;而後進一步使用它。oracle
其餘相似的方法是StringUtils。IsEmpty()和StringUtils.equals()。他們在javadocs中聲稱,若是StringUtils.isNotBlank()拋出NPE,則API中存在錯誤。框架
if
(StringUtils.isNotEmpty(obj.getvalue())){
String s = obj.getvalue();
....
}
|
您應該始終將輸入驗證置於方法的開頭,以使其他代碼沒必要處理輸入錯誤的可能性。所以,若是有人傳遞空值,那麼事情將在堆棧中早點破裂,而不是在較深的位置(根本問題很難識別)中破裂。ide
在大多數狀況下,針對快速故障行爲是一個不錯的選擇。this
當對象引用指向無內容時,將發生空問題。所以,儘量多地使用原語始終是安全的,由於它們不會受到空引用的影響。全部原語都必須附加一些默認值,所以請小心。
雖然鏈式語句很容易在代碼中查看,但它們不是NPE友好的。一條分散在多行中的語句將爲您提供堆棧跟蹤中第一行的行號,不管它出如今何處。
ref.method1().method2().method3().methods4();
這種鏈式語句將僅打印「 行號xyz中發生了NullPointerException」。調試這樣的代碼確實很難。避免此類呼叫。
若是必須打印任何對象的字符串表示形式,請不要使用object.toString()。這是NPE的很是軟的目標。而是使用String.valueOf(object)。
即便object在第二種方法中爲null,它也不會給出異常,而且將輸出null來輸出流。
避免NPE的一個很棒的技巧是返回空字符串或空集合,而不是返回null。在您的應用程序中一致地執行此操做。您會注意到,若是這樣作,則不須要進行大量的空檢查。
例如:
List<string> data =
null
;
@SuppressWarnings
(
"unchecked"
)
public
List getDataDemo()
{
if
(data ==
null
)
return
Collections.EMPTY_LIST;
//Returns unmodifiable list
return
data;
}
|
使用上述方法的用戶即便錯過了空檢查,也不會看到難看的NPE。
我已經看到一些方法聲明,其中方法須要兩個或多個參數。若是參數之一做爲null傳遞,則方法以某種不一樣的方式起做用。避免這種狀況。
相反,您應該定義兩種方法;一個帶有單個參數,第二個帶有兩個參數。強制傳遞參數。當您在方法內部編寫應用程序邏輯時,這頗有幫助,由於您能夠確保方法參數不會爲null。所以,您不會放置沒必要要的假設和斷言。
代替在下面的代碼中編寫字符串比較
public
class
SampleNPE {
public
void
demoEqualData(String param) {
if
(param.equals(
"check me"
)) {
// some code
}
}
}
|
像這樣寫上面的代碼。即便參數做爲null傳遞,這也不會在NPE中引發。
public
class
SampleNPE {
public
void
demoEqualData(String param) {
if
(
"check me"
.equals(param))
// Do like this
{
// some code
}
}
}
|
instanceof運算符是NPE安全的。所以,instanceof null老是返回false。它不會致使NullPointerException。若是您記住這一事實,則能夠消除混亂的條件代碼。
// Unnecessary code
if
(data !=
null
&& data
instanceof
InterestingData) {
}
// Less code. Better!!
if
(data
instanceof
InterestingData) {
}
|
若是您要處理靜態變量或靜態方法,則即便您的引用變量指向null,也不會獲得null指針異常,由於靜態變量和方法調用是在編譯時根據類名綁定的,而且與對象無關
MyObject obj =
null
;
String attrib = obj.staticAttribute;
//no NullPointerException because staticAttribute is static variable defined in class MyObject
|
Joshua bloch在有效的Java中說:「能夠說,全部錯誤的方法調用均可以歸結爲非法論點或非法狀態,可是其餘例外一般用於某些種類的非法論據和狀態。若是調用者在某個參數中傳遞了null,而該參數禁止使用null值,則約定NullPointerException
將拋出而不是IllegalArgumentException
。
所以,若是必須NullPointerException
在代碼的某些地方容許使用,則請確保使它們比一般具備更多的信息性。看下面的例子:
package
com.howtodoinjava.demo.npe;
public
class
SampleNPE {
public
static
void
main(String[] args) {
// call one method at a time
doSomething(
null
);
doSomethingElse(
null
);
}
private
static
String doSomething(
final
String param) {
System.out.println(param.toString());
return
"I am done !!"
;
}
private
static
String doSomethingElse(
final
String param) {
if
(param ==
null
) {
throw
new
NullPointerException(
" :: Parameter 'param' was null inside method 'doSomething'."
);
}
System.out.println(param.toString());
return
"I am done !!"
;
}
}
|
這兩個方法調用的輸出是這樣的:
Exception in thread
"main"
java.lang.NullPointerException
at com.howtodoinjava.demo.npe.SampleNPE.doSomething(SampleNPE.java:
14
)
at com.howtodoinjava.demo.npe.SampleNPE.main(SampleNPE.java:
8
)
Exception in thread
"main"
java.lang.NullPointerException: :: Parameter
'param'
was
null
inside method
'doSomething'
.
at com.howtodoinjava.demo.npe.SampleNPE.doSomethingElse(SampleNPE.java:
21
)
at com.howtodoinjava.demo.npe.SampleNPE.main(SampleNPE.java:
8
)
|
顯然,第二個堆棧跟蹤更有用,而且使調試容易。