请考虑以下Java源代码:
if( agents != null ) {
for( Iterator iter = agents.keySet().iterator(); iter.hasNext(); ) {
// Code that uses iter.next() ...
//
}
}
Run Code Online (Sandbox Code Playgroud)
这agents
是一个HashMap
.
为什么for
声明有时会抛出NullPointerException
?
谢谢.
线程安全
如果您的代码是多线程的,那么它是可能的.例如:
public class C {
private Hashtable agents = new Hashtable();
public iterate() {
if( agents != null ) {
for (Iterator iter = agents.keySet().iterator(); iter.hasNext();) {
// Code goes here
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果另一个线程设置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
}
}
}
Run Code Online (Sandbox Code Playgroud)
迭代代理的代码不再需要检查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();
}
}
Run Code Online (Sandbox Code Playgroud)
这将允许子类(由其他开发人员编写)替换他们自己使用的抽象数据类型的子类(允许系统更灵活地保持开放 - 封闭原则),而不必修改(或复制/浪费)您的原始工作.
这不应该是一个循环?
if (agents != null) {
Iterator iter = agents.keyset().iterator();
while (iter.hasNext()) {
//some stuffs here
}
}
Run Code Online (Sandbox Code Playgroud)
或每个?
if (agents != null) {
//Assuming the key is a String
for (String key : agents.keyset()) {
//some stuffs here
}
}
Run Code Online (Sandbox Code Playgroud)