为什么这段代码有时会抛出NullPointerException?

时间:2010-03-16 21:16:47

标签: java hashmap

考虑以下Java源代码:

if( agents != null ) {
  for( Iterator iter = agents.keySet().iterator(); iter.hasNext(); ) {
    // Code that uses iter.next() ...
    //
  }
}

agentsHashMap

为什么for语句有时会抛出NullPointerException

谢谢。

3 个答案:

答案 0 :(得分:7)

线程安全

如果你的代码是多线程的,那么它是可能的。例如:

public class C {
  private Hashtable agents = new Hashtable();

  public iterate() {
    if( agents != null ) {
      for (Iterator iter = agents.keySet().iterator(); iter.hasNext();) {
        // Code goes here
      }
    }
}

如果另一个线程在agents语句执行后(但在null循环之前)立即将if设置为for,那么您将获得NullPointerException 。通过使用访问器(结合延迟初始化)避免这种情况。

另外,正如其他人所提到的那样,如果可能的话,避免使用这种循环结构来支持泛型。有关详细信息,请参阅其他答案。

访问者提供保护

如果您始终使用以下模式,则源代码中永远不会有NullPointerException(另一方面,第三方代码可能会出现导致代码失败的问题,间接失败,这不是容易避免)。

public class C {
  private Hashtable agents;

  private synchronized Hashtable getAgents() {
    if( this.agents == null ) {
      this.agents = new Hashtable();
    }

    return this.agents;
  }

  public iterate() {
    Hashtable agents = getAgents();

    for (Iterator iter = agents.keySet().iterator(); iter.hasNext();) {
      // Code goes here
    }
  }
}

迭代代理的代码不再需要检查null。由于许多原因,此代码更加强大。您可以将Hashmap(或任何其他抽象数据类型,例如ConcurrentHashMap<K,V>)替换为Hashtable

开放原则

如果你对自己的时间感到特别慷慨,你可以去:

public class C {
  private Hashtable agents;

  private synchronized Hashtable getAgents() {
    if( this.agents == null ) {
      this.agents = createAgents();
    }

    return this.agents;
  }

  public iterate() {
    Iterator i = getAgentKeyIterator();

    while( i.hasNext() ) {
      // Code that uses i.next() ...
    }
  }

  protected Hashtable createAgents() {
    return new Hashtable();
  }

  private Iterator getAgentKeyIterator() {
    return getAgentKeys().iterator();
  }

  private KeySet getAgentKeys() {
    return getAgents().keySet();
  }
}

这将允许子类(由其他开发人员编写)替换他们自己使用的抽象数据类型的子类(允许系统更灵活地与Open-Closed Principle保持一致),而无需修改(或复制/浪费你原来的工作。

答案 1 :(得分:5)

这不应该是一个while循环吗?

if (agents != null) {
    Iterator iter = agents.keyset().iterator();
    while (iter.hasNext()) {
        //some stuffs here
    }
}

或每个人?

if (agents != null) {
    //Assuming the key is a String
    for (String key : agents.keyset()) {
        //some stuffs here
    }
}

答案 2 :(得分:0)

确保没有在循环内将iter设置为null。