看完问题鸭哥想说,NullPointerException 确实不讲武德,小伙子大意了没有闪,鸭哥来帮你解决~
题目如下:
//不讲武德的代码 public class Printer { private String name; public void setName(String name) { this.name = name; } public void print() { printString(name); } private void printString(String s) { System.out.println(s + " (" + s.length() + ")"); } public static void main(String[] args) { Printer printer = new Printer(); printer.print(); } }
运行结果:
Exception in thread "main" java.lang.NullPointerException at Printer.printString(Printer.java:13) at Printer.print(Printer.java:9) at Printer.main(Printer.java:19)
根据报错信息(stacktrace),可以顺藤摸瓜,找出问题所在:
- 程序的编译没有问题,编译后运行,线程"main"抛出了 NullPointerException 空指针异常;
- 继续往下看,新建的对象 printer 调用 printString 方法时,第 13 行代码抛出了异常,出现问题的代码是 s.length() ;
- 执果索因,printString 方法中,s 的值从何而来呢?是在 print() 方法中通过 调用printString(name) 传入的。检查后可以发现,问题在于 this.name 为 null;
- 问题找到了,由于新建对象时没有初始化,调用了 null 的实例方法,导致抛出了异常。
正确的代码如下:
public class Printer { private final String name; public Printer(String name) { this.name = Objects.requireNonNull(name); } public void print() { printString(name); } private void printString(String s) { System.out.println(s + " (" + s.length() + ")"); } public static void main(String[] args) { Printer printer = new Printer("123"); printer.print(); } }
故事到这里似乎就结束了,但俗话说吃一堑长一智,鸭哥还是要继续扒一下 NullPointerException 。
在Java中,当我们用如下方式声明一个基本数据类型的变量时。
int x; x = 1;
第一行,声明了 int 型变量 x,且 Java 会将 x 的值初始化为 0;
第二行,将 10 赋值给 x,10这个数值会被写入变量 x 指向的内存中。但当我们用类似的方式声明一个引用数据类型的对象时,Java执行的操作并不相同
Integer num; num = new Integer(1);
第一行,声明了 num 变量,但因为 Integer 属于引用类型,此时 num 并不包含数值,而是一个指针,并且指针的值为 null, 即空指针,不指向任何地址;
第二行,先是创建了一个 Integer 对象,然后将 num 变量指向了该对象。
当我们声明了一个引用类型的变量,却没有创建指向该变量的对象,此时访问这个变量的内容或调用它的实例方法,就会抛出 NullPointerException (NPE) 异常,因为我们要访问的内容实际上并不存在。
常见的处理方式是,先判断参数是否为空,非空时再进行接下来的处理,模式如下:
public void doSomething(someObject obj) { if(obj == null) { // Do something } else { // Do something else } }
最后,鸭哥想说,应对 NullPointerException (NPE) 的最有效方法就是:
所有不是我们自己创建的对象,一律检查该对象是否为空
如果是调用者给某方法传入了无效参数,最好将抛出的异常返回给调用者。忽略无效参数且不做任何处理是最不可取的,因为这样做隐藏了问题,后续出错时再排查会相当困难。
关于 NullPointerException,你有哪些注意事项想要分享给大家呢?