Ответ 1
Безопасность потоков
Если ваш код многопоточен, тогда это возможно. Например:
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();
}
}
Это позволит подклассам (написанным другими разработчиками) заменить свой собственный подкласс используемого абстрактного типа данных (позволяя системе большую гибкость в соответствии с Принцип открытого закрывания), без необходимости изменять (или копировать/тратить) свою оригинальную работу.