问题描述
如果您的代码是多线程的,则有可能。例如:
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
源代码中将永远不会包含s(另一方面,第三方代码可能会间接导致某些原因导致代码失败,这很难避免)。
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();
}
}
这将允许子类(由其他开发人员编写)替换他们自己的正在使用的抽象数据类型的子类(使系统在遵循开放式封闭原则的情况下具有更大的灵活性),而无需修改(或复制/浪费)原始的工作。
解决方法
考虑以下Java源代码:
if( agents != null ) {
for( Iterator iter = agents.keySet().iterator(); iter.hasNext(); ) {
// Code that uses iter.next() ...
//
}
}
该agents
是HashMap
。
为什么该for
语句有时会抛出NullPointerException
?
谢谢。