2010-07-11 6 views
8

Tenir compte cet extrait de code:meilleures pratiques pour retour des références d'objets

class MyClass{ 
    private List myList; 
    //... 
    public List getList(){ 
     return myList; 
    } 
} 

Comme Java passe références d'objets par valeur, je crois comprendre que tout objet appelant getList() va obtenir une référence à myList, lui permettant de modifier myList malgré c'est private. Est-ce exact?

Et, si elle est correcte, devrais-je utiliser

return new LinkedList(myList); 

pour créer une copie et passer de nouveau une référence à la copie plutôt que l'original, afin d'empêcher l'accès non autorisé à la liste référencée par myList?

+2

techniquement, aucun client externe ne pourra changer la valeur du champ myList dans votre classe. Ce sera toujours un handle/référence à List, référençant la liste à laquelle un code dans MyClass l'a défini.Le client externe sera en mesure de modifier le contenu de cette liste –

+0

Oui, c'est ce que je voulais dire, mais je me suis un peu bâclé avec mon explication. Je vais l'éditer – chrisbunney

+0

+1 Miro A pour une clarification correcte. Et oui, votre solution en créant une copie de la liste est correcte (pour ce que vous voulez réaliser). – xagyg

Répondre

9

Je fais ça. Mieux encore, parfois je renvoie une copie non modifiable en utilisant l'API Collections.

Si vous ne le faites pas, votre référence n'est pas privée. Toute personne ayant une référence peut modifier votre état privé. La même chose est vraie pour toute référence mutable (par exemple, Date).

+3

Si vous fournissez une vue non modifiable de la collection d'origine, sachez que toute modification de la liste d'origine sera reflétée dans la vue. La vie serait tellement plus simple avec des collections immuables ... –

2

Cela dépend de ce que vous voulez.

Voulez-vous exposer la liste et faire en sorte que les gens puissent l'éditer?

Ou voulez-vous laisser les gens le regarder, mais ne pas le modifier?

Il n'y a pas de bonne ou de mauvaise manière dans ce cas. Cela dépend juste de vos besoins de conception.

+0

Donc, si votre design dicte qu'un attribut a une visibilité privée, vous devriez retourner une copie de l'objet plutôt qu'une simple référence pour vous assurer qu'il reste encapsulé – chrisbunney

+0

@chris Si vous concevez exige que les gens ne devraient pas être en mesure de modifier votre liste, puis en transmettre une copie. Sinon, passez la référence d'origine. – jjnguy

+1

Oui, désolé, c'était un commentaire rhétorique, j'ai compris votre réponse;) – chrisbunney

1

Il peut y avoir des cas où l'on voudrait retourner la liste "brute" à l'appelant. Mais en général, je pense que c'est une mauvaise pratique car elle casse l'encapsulation et est donc contre OO. Si vous devez retourner la liste "brute" et non une copie, elle doit être explicitement claire pour les utilisateurs de MyClass.

0

Oui, et il a un nom .. "Copie défensive". La copie à la réception est également recommandée. Comme Tom has noted, le comportement du programme est beaucoup plus facile à prévoir si la collection est immuable. Donc, sauf si vous avez une très bonne raison, vous devriez utiliser une collection immuable.

Lorsque Google Guava devient une partie de la bibliothèque standard Java (je pense tout à fait, il devrait), ce serait probablement devenu l'idiome préféré:

return ImmutableList.copyOf(someList); 

et

void (List someList){ 
    someList = ImmutableList.copyOf(someList); 

Cela a un avantage supplémentaire de performances, car la méthode copyOf() vérifie si la collection est déjà une instance de la collection immutable (instanceof ImmutableList) et si tel est le cas, ignore la copie.

1

Je pense que le modèle de rendre les champs privés et fournir des accesseurs est simplement destiné à l'encapsulation de données. Si vous voulez que quelque chose soit vraiment privé, ne lui donnez pas de méthodes d'accesseur! Vous pouvez ensuite écrire d'autres méthodes qui renvoient des versions immuables de vos données privées ou de leurs copies.