2010-03-16 4 views

Répondre

7

Sécurité des threads

Si votre code est multi-thread, il est alors possible. Par exemple:

public class C { 
    private Hashtable agents = new Hashtable(); 

    public iterate() { 
    if(agents != null) { 
     for (Iterator iter = agents.keySet().iterator(); iter.hasNext();) { 
     // Code goes here 
     } 
    } 
} 

Si un autre thread met à agentsnull immédiatement après la déclaration exécute if (mais avant la boucle for), alors vous obtiendrez un NullPointerException. Évitez cela en utilisant des accesseurs (combinés avec une initialisation paresseuse).

Aussi, comme d'autres l'ont mentionné, évitez de telles constructions en boucle en faveur de génériques, si possible. Voir d'autres réponses pour plus de détails.

accesseurs offrent une protection

Si vous utilisez toujours le schéma suivant, vous aurez jamais NullPointerException s dans votre code source (code tiers, d'autre part, pourrait avoir des problèmes qui causent votre code à l'échec indirectement, ce qui ne peut être facilement évité).

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 
    } 
    } 
} 

Le code qui itère sur les agents n'a plus besoin de vérifier null. Ce code est beaucoup plus robost pour plusieurs raisons. Vous pouvez remplacer Hashmap (ou tout autre type de données abstrait, tel que ConcurrentHashMap<K,V>) pour Hashtable.

ouvert-fermé Principe

Si vous sentez particulièrement généreux avec votre temps, vous pouvez aller aussi loin que:

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(); 
    } 
} 

Cela permettrait à des sous-classes (écrit par d'autres développeurs) de se substituer à propre sous-classe du type de données abstrait utilisé (permettant au système une plus grande flexibilité en accord avec le Open-Closed Principle), sans avoir à modifier (ou copier/perdre) votre travail original.

+0

Je pense qu'un 'ConcurrentHashMap ' serait préférable à un 'Hashtable'. – Powerlord

+0

Je pense que l'environnement multithread pourrait être une explication plausible, laissez-moi pousser plus autour, merci. – Tiberiu

5

Cela ne devrait-il pas être une boucle while?

if (agents != null) { 
    Iterator iter = agents.keyset().iterator(); 
    while (iter.hasNext()) { 
     //some stuffs here 
    } 
} 

ou un pour chaque?

if (agents != null) { 
    //Assuming the key is a String 
    for (String key : agents.keyset()) { 
     //some stuffs here 
    } 
} 
+1

Mes pensées aussi ...? –

+0

Je dirais qu'une boucle for est plus appropriée pour un Iterator.Je n'utiliserais pas de boucle while car l'Iterator est alors visible pour tout le code après un certain temps. –

+0

@Steve Kuo: Personnellement, j'aime le meilleur pour chaque boucle de style, et je l'utilise au lieu de traiter directement avec Iterator. – Powerlord

0

Assurez-vous de ne pas définir le iter sur null à l'intérieur de la boucle.

Questions connexes