正确的避免NullPointException

2020-06-13

1. 正确使用 String类的 equals()方法 和 Object类的 equals() 方法

已知对象在前,未知对象在后。注意:已知对象不为 null

######正确示例

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String[] args) {
String name = "sungm";
//name为已知对象且被赋予初始值不为空
if (name.equals(getOtherName())) {
//todo do something
System.out.println("todo do something");
}
}

private static String getOtherName() {
return "sungm";
}

######错误示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void main(String[] args) {

String name = "sungm";
//getOtherName()方法返回值为 null。抛出NPE
if (getOtherName().equals(name)) {
//todo do something
System.out.println("todo do something");
}

}

private static String getOtherName() {
return null;
}

2. 未知对象转String使用String.valueOf()方法

空对象调用 toString() 方法会抛出NPE,使用 String.valueOf() 替代

#####示例

1
2
3
4
5
6
7
8
9
10
public static void main(String[] args) {
//抛NPE
System.out.println(getPrice().toString());
//不抛NPE
System.out.println(String.valueOf(getPrice()));
}

private static BigDecimal getPrice() {
return null;
}
String.valueOf() 方法源码
1
2
3
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}

3. 使用第三方类库或者自己封装的工具类

例如 Apache 的 StringUtils 类

#####Apache 的 StringUtils工具类部分源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

public static boolean isEmpty(String str) {
return str == null || str.length() == 0;
}

public static boolean isNotEmpty(String str) {
return !isEmpty(str);
}

public static boolean isBlank(String str) {
int strLen;
if (str != null && (strLen = str.length()) != 0) {
for(int i = 0; i < strLen; ++i) {
if (!Character.isWhitespace(str.charAt(i))) {
return false;
}
}

return true;
} else {
return true;
}
}

public static boolean isNotBlank(String str) {
return !isBlank(str);
}

#####Apache 中 StringUtils 中 isEmpty() 方法 和 isBlank() 方法的区别:

1: isEmpty() 方法:当Sting为null或者空(””)时返回true
2: isBlank() 方法 :当Sting为null或者空(””)或者空字符串(” “)时返回true

#####示例

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String[] args) {

String empty = null;
System.out.println(StringUtils.isEmpty(empty));

empty = "";
System.out.println(StringUtils.isEmpty(empty));

empty = " ";
System.out.println(StringUtils.isBlank(empty));

}

4. 避免自动拆箱可能抛出NPE

自动拆箱可能抛出NPE

1
2
3
4
//反例
public int function() {
return Integer对象;
}

5. 数据库查出的数据可能为null,做空判断

数据库非空字段可以加非空约束;对可能为空的字段做空判断、防止NPE。


6. 级联调用容易抛出NPE,建议使用Java 8 的 Optional类

例如 object.getMehtodA().getMethodB().getMethodC();很容易抛出NPE


7. 远程调用返回对象容易抛出NPE,建议做空判断

调用第三方接口等返回对象可能为空,建议对该对象操作之前做空判断。


8. 取Session中 的值之前做空判断

取Session的值之前对Session做空判断,对获取的Session值操作之前对Session值做空判断、避免NPE


9. 对集合的操作之前做空判断

取集合中的值之前对集合做空判断,对获取的集合值操作之前对集合值做空判断、避免NPE