Mise en situation
L’API Java semble nous offrir la possibilité de rendre une liste non-modifiable. Cette fonctionnalité est pratique, par exemple, lorsqu’on rédige une librairie destinée à être utilisée par plusieurs projets et qu’on souhaite empêcher les ajouts ou les suppressions par le programme utilisant cette librairie.
Voici un exemple d’utilisation :
List list = new ArrayList(); list.add("A"); list.add("B"); list.add("C"); List unmodifiableList = Collections.unmodifiableList(list); // Cette instruction va déclencher une java.lang.UnsupportedOperationException unmodifiableList.put("D");
Description du piège
Il faut bien comprendre ce qui se passe sur la ligne « Collections.unmodifiableList(list); » pour comprendre d’où provient le piège. Cette instruction encapsule la liste modifiable dans une liste non-modifiable. Ainsi, chaque demande de modification va être bloquée par la classe qui encapsule, alors que chaque demande de lecture va être transférée à la classe encapsulée.
Dans notre exemple le piège peut arriver si on garde la référence « list » pour l’utiliser dans un autre traitement. En appelant la méthode « add(…) » directement sur l’objet « list », un élément va être ajouté à l’objet « list » mais sera également accessible via l’objet « unmodifiableList ».
Ainsi, la liste « unmodifiable » a donc été modifiée indirectement.
Code source de démonstration
import java.util.ArrayList; import java.util.Collections; import java.util.List; public class Main { public static void main(String[] args) { List list = new ArrayList(); list.add("A"); list.add("B"); list.add("C"); // On crée la liste non-modifiable List unmodifiableList = unmodifiableList = Collections.unmodifiableList(list); System.out.println("--------------------------------------------"); System.out.println("unmodifiableList = " + unmodifiableList); System.out.println("--------------------------------------------"); // On ajoute 2 éléments à la liste modifiable list.add("D"); list.add("E"); // On lit la liste non-modifiable int count = unmodifiableList.size(); for (int i = 0; i < count; i++) { System.out.println("read : " + unmodifiableList.get(i)); } } }
Résultat
-------------------------------------------- unmodifiableList = [A, B, C] -------------------------------------------- read unmodifiableList[0] : A read unmodifiableList[1] : B read unmodifiableList[2] : C read unmodifiableList[3] : D read unmodifiableList[4] : E
2 réflexions sur “Java : Le piège des listes "unmodifiable"”
En effet Guava offre plusieurs « Immutable… » (List, Map, Set, etc.) qui permettent de limiter la modification d’une liste.
Il faut par contre bien garder en tête qu’on limite la modification de la liste mais pas des objets qu’elle contient.
La libairie Guava permet d’éviter ce piège avec ImmutableList.copyOf(originalList);
Un petit article sur DZone qui traite aussi de cas des Set :
http://java.dzone.com/articles/immutable-collections-guava
Les commentaires sont fermés.