今天在写代码的时候遇到一个很怪异的空指针异常,大概代码如下
public class User {
private Integer id;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
}
User user = new User();
Integer id = user == null ? 0 : user.getId();
System.out.println(id);
看代码应该不会有问题,但是运行的时候报了java.lang.NullPointerException异常。查看编译后的代码如下
User user = new User();
Integer id = Integer.valueOf(user == null ? 0 : user.getId().intValue());
System.out.println(id);
可以看到拆箱和装箱是java代码的语法糖, 是在编译阶段完成的。在编译阶段,在运算中有不同的类型,涉及到类型转换,编译器会优先考虑向下转型,就是把对象类型转换为基本类型在进行计算。 因为user.getId()为null,调用null的intValue()方法抛出空指针异常。下面这两种情况不会报错
User user = new User();
Integer id = user == null ? 0 : null;
System.out.println(id);
User user = new User();
Integer id = user == null ? Integer.valueOf(0) : user.getId();
System.out.println(id);
第一种情况是编译器发现向下转型为报错,就向上转型,把0转成Integer.valueOf(0), 第二种是都是对象类型,不需要转型。编译后的结果分别为
User user = new User();
Integer id = user == null ? Integer.valueOf(0) : null;
System.out.println(id);
User user = new User();
Integer id = user == null ? Integer.valueOf(0) : user.getId();
System.out.println(id);
总结:
在三元表示式中,尽量使用同一种类型。不要基本类型和对象类型混用。