Java : Le piège des listes "unmodifiable"

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"”

  1. OlivierPerez

    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.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *