Java基础干货12种方法让你彻底告别空指针异常
Posted 在路上的德尔菲
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java基础干货12种方法让你彻底告别空指针异常相关的知识,希望对你有一定的参考价值。
🤔What 什么是空指针NullPointerException(NPE)
空指针是运行时异常,所以就导致在编码时不易发现,因为Java中对象可以设为null,当去使用为null的对象操作时会抛出空指针,NullPointerException 官方解释👇
NullPointerException is a RuntimeException. In Java, a special null value can be assigned to an object reference. NullPointerException is thrown when an application attempts to use an object reference that has the null value. These include:
- Calling the instance method of a null object.
- Accessing or modifying the field of a null object.
- Taking the length of null as if it were an array.
- Accessing or modifying the slots of null as if it were an array.
- Throwing null as if it were a Throwable value.
public class NullPointerException extends RuntimeException {
private static final long serialVersionUID = 5162710183389028792L;
public NullPointerException() {
super();
}
public NullPointerException(String s) {
super(s);
}
}
😲Why 为什么要避免
公司内部 CaseStudy 平台有很多空指针引起的事故,其中一个涉及金额为1,819,172元,退款订单数1662,客诉50+,一行代码可以造成这么大的影响…
可以说这是一个编程中出现最频繁的bug,有人说70%以上的异常都是NullPointerException
如果编码不小心,可能会造成很大的损失,但只要养成好的编码习惯,NPE就不会出现
😈How 消灭NPE
1、已知对象放前
总是从已知的非空String对象中调用equals()方法,equals()方法是对称的,a.equals(b)与b.equals(a)是完全相同的,这是避免空指针的最常见的技巧
//错误方式❌
if(ObjectA.equals("ObjectB")){
.....
}
//正确方式✅
if(”ObjectB“.equals(ObjectA)){
.....
}
//正确方式✅
Boolean.TRUE.equals(a);
2、对象判空
Objects.equals(obj1,obj2);
-------------------------------------------
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
3、使用contains()/containsKey()/containsValue()时注意
HashMap<Object, Object> map = null;
//错误示范❌
Object test = map.get("test");
//错误示范❌
if (map.containsKey("test")){
System.out.println(map.get("test"));
}
4、使用 concat()/trim()时注意
String str = null;
//错误示范❌
str.concat("hello");
//错误示范❌
str.trim();
5、valueOf()与toString()返回相同结果时,使用前者
调用null对象的toString()会抛出空指针异常,而使用valueOf()可以获得相同的值,传递一个null给valueOf()将会返回null,Integer,Double,BigDecimal
String s = null;
//错误方式❌
System.out.println(s.toString());
//正确方式✅
System.out.println(String.valueOf(s));
----------------------------------
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
6、不必要的自动包装和自动解包
如果wrapper类对象是null,自动包装同样容易导致空指针异常,以及int 与Integer类型
public class Student {
private Integer age;
private String name;
public Student(String name) {
this.name = name;
}
//setter and getter
}
Student student = new Student("ram");
// NullPointerException
int age = student.getAge();
// 返回null
Integer age = student.getAge();
7、使用工具类StringUtils,包括对null对象的判断
//使用工具库
System.out.println(StringUtils.isEmpty(null)); //true
System.out.println(StringUtils.isBlank(null)); //true
System.out.println(StringUtils.isNumeric(null)); //false
System.out.println(StringUtils.isAllUpperCase(null)); //false
8、先创建空集合
通过返回一个空的集合或者空数组,避免返回的是空集合而不是null,在确保调用size(),length()的时候不会因为返回的是null ,可用@NotNull 注解
Map emptyMap = Collections.EMPTY_MAP;
Set emptySet = Collections.EMPTY_SET;
List emptyList = Collections.EMPTY_LIST;
9、集合正确判空方式
Apache Commons Lang 包中CollectionUtils类可以帮助快速判空,集合可能为空
//错误方式❌
if(list.size() > 0){
//do something
}
if(CollectionUtils.isEmpty(list)){
//do something
}
-------------------------------------------
public static boolean isEmpty(Collection coll) {
return (coll == null || coll.isEmpty());
}
10、对遍历的数组和集合进行判空
集合和数组可能为null,在进行遍历前先进行判空处理
Collection<Integer> myNumbers = buildNumbers();
//正确方式✅
if (CollectionUtils.isNotEmpty(myNumbers)) {
for (Integer myNumber : myNumbers) {
System.out.println(myNumber);
}
}
11、Optional
一连串调用如obj.getA().getB().getC() ,容易出现NPE,且通过下面格式判断的话影响代码可读性,可使用Java 8 中Optional,感兴趣同学可自行搜索
if (user != null) {
Address address = user.getAddress();
if (address != null) {
Country country = address.getCountry();
if (country != null) {
String isocode = country.getIsocode();
if (isocode != null) {
isocode = isocode.toUpperCase();
}
}
}
}
Optional目的是即保证程序健壮性的同时,又保持代码的优雅和可读性
String str= Optional.ofNullable(getMsgFormDB())
.map(d->d.trim())
.map(d->d.replace(getMsgFromWebService()))
.map(d->d.trim())
.orElseGet(() -> Strings.EMPTY);
12、监控报警
最后一点不是从代码层面上去消灭,但监控报警是防止空指针造成影响的最后一道防线,为了及时发现问题,一般设置NullPointerException > 1 就应该报警且报警级别高。
😀小结:
一写代码时思考清楚是否可能为空指针,二写完代码后认真检查一遍,三使用插件如 Alibaba Java Coding Guidelines 、FindBugs检查一遍
以上是关于Java基础干货12种方法让你彻底告别空指针异常的主要内容,如果未能解决你的问题,请参考以下文章
SpringBug记录 -- java.lang.NullPointerException在Spring单元测试中遇到的空指针异常及依赖注入异常总结