为什么这段代码有时会抛出一个NullPointerException? [英] Why does this code sometimes throw a NullPointerException?

查看:118
本文介绍了为什么这段代码有时会抛出一个NullPointerException?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下Java源代码:

  if(agents!= null){
for(Iterator iter = agents.keySet()。iterator(); iter.hasNext();){
//使用iter.next()...的代码...
//
}
}



agents 是一个 HashMap



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



谢谢。

解决方案

线程安全

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

  public class C {
private Hashtable agents = new Hashtable();如果(代理!= null){
for(Iterator iter = agents.keySet()。iterator(); iter.hasNext();

public iterate(){
){
// Code goes here
}
}
}

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



另外,正如其他人所提到的,如果可能的话,应避免使用这种循环结构来支持泛型。
$ b 访问者提供的保护

在源代码中您将永远不会有 NullPointerException s(第三方代码可能会导致您的代码间接失败,不能轻易避免)。

  public class C {
private Hashtable agents;

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

返回this.agents;


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

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

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



开放原则

如果你对自己的时间特别慷慨,那么你可以尽量做到这一点:

  public class C {
私有Hashtable代理;

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

返回this.agents;


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

while(i.hasNext()){
//使用i.next()...
}
}
$ b的代码$ b保护Hashtable createAgents(){
返回新的Hashtable();
}

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

私钥KeySet getAgentKeys(){
return getAgents()。keySet();




$ b $ p
$ b $这样可以让子类(由其他开发者编写)用他们自己的正在使用的抽象数据类型的子类来替换(允许系统在保持 Open - 关闭原则),而无需修改(或复制/浪费)您的原作。


Consider the following Java source:

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

The agents is a HashMap.

Why does the for statement sometimes throw a NullPointerException?

Thank you.

解决方案

Thread Safety

If your code is multi-threaded, then it is possible. For example:

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

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

If another thread sets agents to null immediately after the if statement executes (but before the for loop), then you will get a NullPointerException. Avoid this by using accessors (combined with lazy initialization).

Also, as others have mentioned, avoid such looping constructs in favour of generics, if possible. See other answers for details.

Accessors offer Protection

If you always use the following pattern you will never have NullPointerExceptions in your source code (third-party code, on the other hand, might have issues that cause your code to fail, indirectly, which cannot be easily avoided).

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
    }
  }
}

The code that iterates over the agents no longer needs to check for null. This code is much more robost for many reasons. You can substitute Hashmap (or any other abstract data type, such as ConcurrentHashMap<K,V>) for Hashtable.

Open-Closed Principle

If you were feeling especially generous with your time you could go as far as:

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();
  }
}

This would allow subclasses (written by other developers) to substitute their own subclass of the abstract data type being used (allowing the system greater flexibility in keeping with the Open-Closed Principle), without having to modify (or copy/waste) your original work.

这篇关于为什么这段代码有时会抛出一个NullPointerException?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆