我应该多关注NullPointerException吗?

时间:2017-04-07 02:26:45

标签: java

当我使用JUnit测试检查我的编码过程时,我发现有一些问题困扰我。 例如:

List<User> list = userDao.findBy("id",id);
list.get(0).getName();

存在问题。我没有使用任何断言来检查列表在使用之前是否为空,这可能导致NullPointException。但请查看业务逻辑。

当我像这样创建一个新用户时。

if(user!=null){
   userDao.save(user)
}

它应该不为null。因为我在添加一个用户时检查用户不是null,所以我肯定知道用户在数据库中是成功的。

如果我在收到用户时添加了很多内容:

if(list!=null||list.size()>0){...};

在使代码陷入混乱的类似地方。

我应该添加还是不添加?如何做出选择? 无论如何。不过。

2 个答案:

答案 0 :(得分:0)

我认为您要找的是方法preconditions,或者更常见的是contracts

让我们假设你的代码被分成许多小方法,应该是这样。然后为每个方法定义前置条件和后置条件。这些都需要得到满足,否则就会出现失败。如果你一直这样做,那么把这些检查放在哪里的问题将以非常直观的方式回答自己。

作为一个例子,让我们考虑两种方法来编写一个用User做某事的方法:

private void doSomethingWithUser(User u) {
  if (u == null) {
    /* take appropriate steps */
  }
  /* perform some action on the user object */
}

上面,该方法负责空值检查。因此,调用代码不需要这样做。

/* 
 * Does this and that with the User.
 * Precondition: the User `u` may not be null!
 */
private void doSomethingWithUser(User u) {
    /* perform some action on the user object */
}

此处,该方法不会检查u null,但是阅读评论后,我们可以看到这就是该方法的设计方式。调用代码负责提交非null对象,否则行为将是未定义的。

当然,现在你面临着何时决定采用哪种方式的决定。显然,您可以为方法设置前提条件让它们仍然执行适当的检查。然后,他们可以返回一个指示错误或抛出异常的值,这很常见。

修改

  

但如果在使用之前需要检查很多对象?我应该检查它们吗?

考虑一下:

public class SimpleClass {
  public static void main (String[] args) {
    User sware = new User("sware");
    User domdom = new User("domdom");

    doSomethingWithUser(sware);
    doSomethingWithUser(domdom);
  }
}

在这里,我们声明main方法中初始化两个对象。我们知道它们不是空的。然后我们马上使用它们。无论该方法是否检查null,我都不会在外面执行此类检查 - 这些对象无法null

现在,想象一下我们有一个更复杂的代码:

public class VeryComplexClass extends ComplexClass implements ComplexInterface {
  /* ... */
  @Override
  private boolean doSomethingWithUser(User u) {
    if (u == null) {
         return false;    
    }
    /* ... */
  }
}

假设我们需要实现doSomethingWithUser()方法来满足接口。或者该方法来自父类,我们覆盖它。我们不知道u将来自哪里。谁有可能称之为这种方法?来自课外的用户?或者这个方法是否被类本身使用?会被传递成员吗?在这一点上很难说清楚。因此,我建议将null检查到位。

答案 1 :(得分:0)

由于您已经检查过用户是否为空,我不认为您需要担心NullPointerException。只需继续使用该代码