次のJavaソースを検討してください。
if( agents != null ) {
for( Iterator iter = agents.keySet().iterator(); iter.hasNext(); ) {
// Code that uses iter.next() ...
//
}
}
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
}
}
}
ステートメントの実行直後(ただしループの前)に別のスレッドが設定さ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();
}
}
これにより、(他の開発者によって作成された)サブクラスが、使用されている抽象データ型の独自のサブクラスを置き換えることができるようになり(システムがOpen-Closed Principleに準拠する際の柔軟性が高まり)、オリジナルを変更(またはコピー/廃棄)する必要がなくなります。作業。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加