首页 > 代码库 > 避免空指针异常

避免空指针异常

五种原因会造成空指针异常:

1. Calling the instance method of a null object. 
2. Accessing or modifying the field of a null object. 
3. Taking the length of null as if it were an array. 
4. Accessing or modifying the slots of null as if it were an array. 
5. Throwing null as if it were a Throwable value. 

之前只是听大牛说过如何在用equals比较时来规避空指针,但自此从没有探究过其中原因,今天就来看看究竟是怎么回事。

我以String类型为例

 

String a=null;
System.out.println("aa".equals(a)); //输出 false;
System.out.println(a.equals("aa")); //报空指针异常

 

仅仅变了个顺序,为何差距如此之大呢?我们来看看equals()方法的源码

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;  //直接比较对象的地址,地址一样存储的值当然也一样
        }
        if (anObject instanceof String) {  //判断参数对象是否是 String 类型的实例,关键就在这个判断
            String anotherString = (String) anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                            return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

源码相对比较简单,有地址判断、实例判断,最后就是转化为字符数组对相对应的字符进行比较

为什么把可为空的变量放在equals方法比较的后面就没问题呢?我们先来看一段代码

String a=null;
if (a instanceof String) {
    System.out.println("11111");
}else {
    System.out.println("22222");
}  // 返回值为 22222

我定义了一个String 类型的变量 a, 但它却不能通过类实例的判断。关键还是在于a 的值为null,null 可以赋值给任何引用类型变量,并且是引用类型的默认值但是带有null值的引用类型变量,instanceof操作将会返回false。所以说将null作为equals方法 的参数传进去的时候,在if(anObject instanceof String) 这个判断中就返回false了。而一个值为null 的引用型变量不能调用实例方法(非静态方法),可以调用静态方法(静态方法使用静态绑定,不会抛空指针)

这恰恰是第一种空指针的原因:Calling the instance method of a null object.  

所以说在使用equals()方法进行比较时将可能变量作为参数传入,而不是方法的调用者。可以作为一种代码规范

 

避免空指针异常