线程安全
如果您的代码是多线程的,那么这是可能的。例如:
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 语句执行之后(但在for 循环之前)立即将agents 设置为null,那么您将获得NullPointerException。通过使用访问器(结合惰性初始化)来避免这种情况。
另外,正如其他人所提到的,如果可能,请避免使用泛型来支持此类循环构造。有关详细信息,请参阅其他答案。
访问器提供保护
如果您始终使用以下模式,您的源代码中将永远不会有NullPointerExceptions(另一方面,第三方代码可能存在导致您的代码间接失败的问题,这是无法轻易避免的)。
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保持一致),而无需修改(或复制/浪费)你的原创作品。