1、概述
java.lang.NullPointerExceptin
我相信只要你是做java开发的,那就一定遇到过。NullPointerException由RuntimeException派生出来,是一个运行时异常。其意指可能会在运行的时候才会被抛出。一个变量是null,即只有其名,没有实值内容,也没分配内存,对它进行操作就会出现NullPointException。
很多文档上说出现这个异常的原因就是引用为null,导致这个异常,比如这样的:Object obj=null; obj.getClass()
。但是我想说的是,大部分情况是这样(即空引用调用方法等),但是有时也不是。下面我们对String,Integer,Boolean
这三个类做运算,看看能否出现空指针异常。
2、String类型
对String类型做各种运算符操作(只要是String支持的),我们发现符合常规情况,即空引用调用方法出现NullPointerException。
@Test
public void testNullPointerExceptin_String(){
String str = "abc";
String strNull = null;
/**
* 算术运算符,String只能使用+
*/
System.out.println(str+strNull); //abcnull
System.out.println(strNull + str); //nullabc
/**
* 关系运算符,String只能使用 == ,!=
*/
System.out.println(str == strNull); //false
System.out.println(strNull == str); //false
System.out.println(str != strNull); //true
/**
* 位运算符,String 均不能使用
* 逻辑运算符,String 均不能使用
*/
/**
* 赋值运算符,String只能使用=,+=
*/
System.out.println(str = strNull); //null
str = "abc";
System.out.println(strNull = str); //abc
strNull = null;
System.out.println(str += strNull); //abcnull
str = "abc";
System.out.println(strNull += str); //nullabc
strNull = null;
/**
* 其他
*/
System.out.println(str.equals(strNull)); //false
System.out.println(strNull.equals(str)); //NullPointerException
System.out.println(str instanceof String); //true
System.out.println(strNull instanceof String); //false
}
3、Integer类型
从下面的代码可以看出,
Integer
类型除了==、!=、=
这三个运算符外,在执行其他的运算符时,都会有空指针问题。
@Test
public void testNullPointerExceptin2(){
Integer inte = 12;
Integer inteNull = null;
/**
* 算术运算符
*/
System.out.println(inte + inteNull); //NullPointerException
System.out.println(inteNull + inte); //NullPointerException
System.out.println(inte - inteNull); //NullPointerException
System.out.println(inte * inteNull); //NullPointerException
System.out.println(inte / inteNull); //NullPointerException
System.out.println(inte % inteNull); //NullPointerException
System.out.println(inteNull++); //NullPointerException
System.out.println(inteNull--); //NullPointerException
/**
* 关系运算符
*/
System.out.println(inte == inteNull); //false
System.out.println(inte != inteNull); //true
System.out.println(inte > inteNull); //NullPointerException
System.out.println(inte < inteNull); //NullPointerException
System.out.println(inte >= inteNull); //NullPointerException
System.out.println(inte <= inteNull); //NullPointerException
/**
* 位运算符
*/
System.out.println(inte & inteNull); //NullPointerException
System.out.println(inte | inteNull); //NullPointerException
System.out.println(inte ^ inteNull); //NullPointerException
System.out.println(inte << inteNull); //NullPointerException
System.out.println(inte >> inteNull); //NullPointerException
System.out.println(inte >>> inteNull); //NullPointerException
System.out.println(~inteNull); //NullPointerException
/**
* 逻辑运算符,Integer不能使用
*/
/**
* 赋值运算符
*/
System.out.println(inteNull = inte); //12
inteNull = null;
System.out.println(inteNull += inte); //NullPointerException
inteNull = null;
System.out.println(inteNull -= inte); //NullPointerException
inteNull = null;
System.out.println(inteNull *= inte); //NullPointerException
inteNull = null;
System.out.println(inteNull /= inte); //NullPointerException
inteNull = null;
System.out.println(inteNull %= inte); //NullPointerException
inteNull = null;
System.out.println(inteNull <<= inte); //NullPointerException
inteNull = null;
System.out.println(inteNull >>= inte); //NullPointerException
inteNull = null;
System.out.println(inteNull &= inte); //NullPointerException
inteNull = null;
System.out.println(inteNull ^= inte); //NullPointerException
inteNull = null;
System.out.println(inteNull |= inte); //NullPointerException
}
4、布尔类型
对于
Boolean
类型,除了赋值运算符=
,其他的都会发生空指针异常。
@Test
public void testNullPointerExceptin3(){
Boolean flag = true;
Boolean flagNull = null;
/**
* 算术运算符
* 关系运算符
*/
/**
* 位运算符
*/
System.out.println(flagNull & flag); //NullPointerException
System.out.println(flagNull | flag); //NullPointerException
System.out.println(flagNull ^ flag); //NullPointerException
/**
* 逻辑运算符
*/
System.out.println(flagNull && flag); //NullPointerException
System.out.println(flagNull || flag); //NullPointerException
System.out.println(!flagNull); //NullPointerException
/**
* 赋值运算符
*/
System.out.println(flagNull = flag); //true
flagNull = null;
System.out.println(flagNull &= flag); //NullPointerException
flagNull = null;
System.out.println(flagNull ^= flag); //NullPointerException
flagNull = null;
System.out.println(flagNull |= flag); //NullPointerException
}
5、总结
- 发生空指针异常的原因除了“空引用操作方法”外,还可能是对空对象执行部分运算符;
instanceof
是安全的,不会发生空指针异常;- 部分类型的空对象进行运算符操作
- 除了“空引用操作方法”导致的空指针异常外。对String类型的空对象执行运算符,一般情况下不会发生空指针异常;
- 除了“空引用操作方法”导致的空指针异常外。对数值类型(
Integer,Float,Double,Byte
等)的空对象执行运算符,除了==、!=、=
这三个运算符外,其他运算符都会发生空指针异常;- 除了“空引用操作方法”导致的空指针异常外。对Boollean类型的空对象执行运算符,除了
=
运算符外,其他运算符都会发生空指针异常。
6、如何避免空指针
- 在使用equals方法时,尽量是
已知量.equals(未知量)
这种,这里的“已知量”可是是常量、枚举等。比如String man="1"; man.equals(people.getSex())";
,而不是String man="1"; people.getSex().equals(man)";
,因为man是常量,而people.getSex()未知,可能为空;- 方法的返回值是null时,尽量创建一个新对象返回,不要直接返回null。比如某个方法的返回值是People,如果发现返回值是null,尽量替换成new People();这样调用方可以避免空指针判断;
- 优先使用String.valueOf()方法代替toString()。当程序代码需要对象的字符串表示形式时,请避免使用该对象的toString方法。如果你的对象的引用等于null,NullPointerException则会抛出,使用静态String.valueOf方法,该方法不会抛出任何异常并打印"null"。但是,这个“null”有时很坑,后端返给前端的字段,如果是null,尽量返回null,而不是“null”;
- 对数值类型的对象进行运算符操作时,尽量先判空。