Java中如何避免空指针异常

移动开发
这对于我来说是一个很合理常见的问题,由初级过度到中级程序员的时候经常会遇到。他们不知道也不信任正在用的约定,并且小心的检查着null。还有当他们写代码的时候,总是会依赖于通过返回空(NULL)来表明某些意义,因此需要调用者去检查Null。

这对于我来说是一个很合理常见的问题,由初级过度到中级程序员的时候经常会遇到。他们不知道也不信任正在用的约定,并且小心的检查着null。还有当他们写代码的时候,总是会依赖于通过返回空(NULL)来表明某些意义,因此需要调用者去检查Null。

换种方式来说,有两种情景空指针的检查会出现:

 

就约定来说是一个合理的响应

不是合理的响应  

第二种很简单,可以通过用assert或者直接允许失败,例如NullPointerException。Assertions是一个从Java1.4加进来的高度未被利用的特性,语法是:

  1. assert <condition> 

或者

  1. assert <condition> : <object> 

condition是一个布尔表达式,object是一个对象(其toString()方法的输出将会被包含在错误里)。

如果condition为false的话,assert将会抛出一个Error(AssertionError).

默认Java会忽略断言你可以通过在JVM中传入一个-ea参数来启用断言,

你可以为单独的一个包或者类启动关闭assertions。这意味着你可以在开发和测试的时候通过断言来验证代码,

在发布产品的时候关闭它,尽管我下面展示的测试中并没有因为assertions而损失性能。

在这个代码段中不用断言也可以,因为他会运行失败的,就像加了断言一样。唯一的区别是

有了断言可能会发生的更快一些,更有意义,并且会附加一些额外的信息,而这可以帮助你弄明白

失败的原因。

***种有一点棘手。如果你对不能控制正在调用的这段代码,那你就卡住了。

如果Null是一个合理的返回值,你就应该检查它。

如果是你能够控制的代码,那就是个完全不同的故事情景了.尽量避免用NULL作为返回值。

对于返回Collections的集合很容易,返回Empty(一个空集合或者数组),而不是一直用null作为返回值。

对于不是返回Collections的方法会有一点复杂。考虑下面这个例子:

  1. public interface Action { 
  2.   void doSomething(); 
  3.  
  4. public interface Parser { 
  5.   Action findAction(String userInput); 

Parser采用用户的输入作为参数,然后做一些事情(例如模拟一个命令行)。现在你可能会

返回null,如果没找到对应输入的动作的话,这就导致了刚才说过的空指针检查。

一个可选的解决方案是永远不要返回null,而是返回一个空对象

  1. public class MyParser implements Parser { 
  2.   private static Action DO_NOTHING = new Action() { 
  3.     public void doSomething() { /* do nothing */ } 
  4.   }; 
  5.  
  6.   public Action findAction(String userInput) { 
  7.     // ... 
  8.     if ( /* we can't find any actions */ ) { 
  9.       return DO_NOTHING; 
  10.     } 
  11.   } 

比较这段代码:

  1. Parser parser = ParserFactory.getParser(); 
  2. if (parser == null) { 
  3.   // now what? 
  4.   // this would be an example of where null isn't (or shouldn't be) a valid response 
  5. Action action = parser.findAction(someInput); 
  6. if (action == null) { 
  7.   // do nothing 
  8. else { 
  9.   action.doSomething(); 

和这段:

  1. ParserFactory.getParser().findAction(someInput).doSomething(); 

这是个更好的设计,因为足够简洁,避免了多余的判断。即便如此,或许比较合适的设计是:findAction()方法之恶杰抛出一个异常,其中包含一些有意义的错误信息-----特别是在这个案例中你依赖于用户的输入。让findAction()方法抛出一个异常而不是简单的产生一个没有任何解释的NullPointerException 要好得多。

  1. try { 
  2.     ParserFactory.getParser().findAction(someInput).doSomething(); 
  3. catch(ActionNotFoundException anfe) { 
  4.     userConsole.err(anfe.getMessage()); 

或者你认为try/catch 的机制太丑了,你的action应该跟用户提供一个反馈而不是什么都不做:

  1. public Action findAction(final String userInput) { 
  2.     /* Code to return requested Action if found */ 
  3.     return new Action() { 
  4.         public void doSomething() { 
  5.             userConsole.err("Action not found: " + userInput); 
  6.         } 
  7.     } 

 

责任编辑:倪明
相关推荐

2023-10-08 11:09:22

Optional空指针

2022-01-19 09:00:00

Java空指针开发

2022-01-04 23:13:57

语言PanicGolang

2019-11-21 08:51:56

Java异常控制流

2021-02-28 21:47:51

Java语法糖算数

2021-05-12 07:03:25

Switch报空指针

2021-11-15 06:56:45

系统运行空指针

2024-02-28 09:03:20

Optional空指针Java

2024-02-01 12:09:17

Optional容器null

2015-10-10 11:23:17

Java常量反模式

2015-09-22 10:56:13

Java反模式

2017-10-25 20:52:03

内核权限空指针异常

2020-08-20 08:23:52

VueDOM运算符

2024-10-15 15:58:11

2015-01-05 10:01:20

Java

2020-11-02 07:43:33

前端空指针数据

2024-04-02 11:22:01

死锁Java并发

2009-06-22 15:01:00

java项目常见错误

2024-08-12 08:28:35

2020-04-10 10:22:12

Java判空编程语言
点赞
收藏

51CTO技术栈公众号