五分钟学Java:什么是 NullPointerException

第二行代码中,new 关键字创建了一个 Integer 类型的对象,并将变量 num 指向该对象。

当我们声明了一个变量,却没有将该变量指向任何创建的对象,然后就使用它的时候,NullPointerException 就发生了。大多数情况下,编译器会发现这个问题,并且提醒我们“xxxx may not have been initialized”。

假如有这样一段代码:

public void doSomething(SomeObject obj) {

//do something to obj

}

在这种情况下,我们没有创建对象 obj,而是假设它在 doSomething() 方法被调用之前就创建了。

现在假设在此之前它没有创建。我们这样调用 doSomething() 方法:

doSomething(null);

这就意味着 doSomething() 方法的参数 obj 为 null。如果该方法还要使用 obj 继续做点什么,最好提前抛出 NullPointerException,因为开发者需要该信息来进行调试。

还有另外一种替代方法,判断 obj 是不是 null,如果是,就小心行事,做某些不会引起 NullPointerException 的事情;如果不是,就放心大胆地做该做的事情。

/**

  • @param obj An optional foo for ____. May be null, in which case

  • the result will be ____.

*/

public void doSomething(SomeObject obj) {

if(obj != null) {

//do something

} else {

//do something else

}

}

那假如程序真的出现了 NullPointerException,该怎么追踪堆栈信息,找到错误的根源呢?

简单来说,堆栈信息是应用程序在引发 Exception 时调用的方法列表,可以准确地定位到错误发生的根源。就像下面这样。

Exception in thread “main” java.lang.NullPointerException

at com.example.myproject.Book.getTitle(Book.java:16)

at com.example.myproject.Author.getBookTitles(Author.java:25)

at com.example.myproject.Bootstrap.main(Bootstrap.java:14)

就上面这个堆栈信息来说,错误发生在“at …”列表处,第一个“at 处”就是错误最初发生的位置。

at com.example.myproject.Book.getTitle(Book.java:16)

为了调试,我们可以打开 Book.java 类的第 16 行,它可能是:

15   public String getTitle() {

16      System.out.println(title.toString());

17      return title;

18   }

从这段代码中可以看得出,错误的原因很可能是因为 title 为 null。

有时候,应用程序会捕获一个异常,然后把它作为另外一种类型的异常抛出。就像下面这样:

34   public void getBookIds(int id) {

35      try {

36         book.getId(id);    // 这里可能会引发 NullPointerException

37      } catch (NullPointerException e) {

38         throw new IllegalStateException(“A book has a null property”, e)

39      }

40   }

此时的堆栈信息可能是下面这样的:

Exception in thread “main” java.lang.IllegalStateException: A book has a null property

at com.example.myproject.Author.getBookIds(Author.java:38)

at com.example.myproject.Bootstrap.main(Bootstrap.java:14)

Caused by: java.lang.NullPointerException

at com.example.myproject.Book.getId(Book.java:22)

at com.example.myproject.Author.getBookIds(Author.java:36)

… 1 more

和之前堆栈信息有所不同的是,这里多了一个“Caused by”;有时候还会有更多的“Caused by”。在这种情况下,我们通常需要追本溯源,找到最深层次的那个“cause”——它就是堆栈信息中最下面的那个。

Caused by: java.lang.NullPointerException <-- 根本原因

at com.example.myproject.Book.getId(Book.java:22)

同样,我们需要查看一下 Book.java 的第 22 行,找到可能引发 NullPointerException 的原因。

有时候,堆栈信息要比上面的例子凌乱得多。参考下面这个。

javax.servlet.ServletException: Something bad happened

at com.example.myproject.OpenSessionInViewFilter.doFilter(OpenSessionInViewFilter.java:60)

at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)

at com.example.myproject.ExceptionHandlerFilter.doFilter(ExceptionHandlerFilter.java:2 《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 8)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值