14 votes

Liste vs Liste<Objet>

Pourquoi perdons-nous la sécurité des types lorsque nous utilisons List et non en utilisant List<Object> ? Ne s'agit-il pas essentiellement de la même chose ?

EDITAR : J'ai constaté que le texte suivant donne une erreur de compilation

public class TestClass
{
    static void func(List<Object> o, Object s){
        o.add(s);
    }

    public static void main(String[] args){
        func(new ArrayList<String>(), new Integer(1));
    }
}

alors que ce n'est pas le cas

public class TestClass
{
    static void func(List o, Object s){
        o.add(s);
    }

    public static void main(String[] args){
        func(new ArrayList<String>(), new Integer(1));
    }
}

Pourquoi ?

7voto

Mehrdad Points 70493

List est une liste de un type que vous ne connaissez pas . Il pourrait s'agir d'un List<String> , List<Integer> etc.
C'est effectivement équivalent à List<?> ou List<? extends Object> sauf qu'il n'a pas documenter ce fait. Il n'est pris en charge que pour la rétrocompatibilité.

List<Object> es un liste d'objets . Tout objet de tout peut être placé à l'intérieur, contrairement à une List<String> par exemple, qui n'accepte que les chaînes de caractères.

Donc non, ce n'est pas la même chose.

5voto

Mike Samuel Points 54712

Pourquoi perdons-nous la sécurité des types lorsque nous utilisons List et non en utilisant List<Object> ? Ne s'agit-il pas essentiellement de la même chose ?

Non, ce n'est pas la même chose.

Si vous fournissez une API,

class API {
  static List<Object> getList() { ... }
  static void modifyList(List<Object> l) { ... }
}

et qu'un client l'utilise à mauvais escient

List<Integer> list = API.getList();
API.modifyList(list);
for (Integer i : list) { ... }  // Invalid

alors quand votre API spécifie List<Object> ils obtiennent une erreur de compilation, mais ils n'en obtiennent pas lorsque API.getList() renvoie un List y API.modifyList(list) prend un List sans paramètres de type générique.

EDITAR:

Dans les commentaires, vous avez mentionné le changement

void func(List<Object> s, Object c) { s.add(c); }

à

void func(List s, Object c) { s.add(c); }

de sorte que

func(new List<String>(), "");

fonctionnerait.

C'est une violation de la sécurité de type. La manière sûre de faire ceci est

<T> void func(List<? super T> s, T c) { s.add(c); }

ce qui revient à dire que func est une fonction paramétrée qui prend un List dont le type peut être n'importe quelle super classe de T, et une valeur de type T, et ajoute la valeur à la liste.

3voto

RHSeeger Points 9217

A List<Object> n'est pas vraiment plus sûr qu'un fichier de type List . Cependant, le Object dans le code n'implique pas l'intention. Quand quelqu'un d'autre le regardera plus tard, il pourra voir que vous avez choisi délibérément Object comme type, plutôt que de se demander si l'on a oublié de mettre un type ou si l'on stocke quelque chose d'autre et que l'on fait un typecasting ailleurs.

Étant donné que le code est lu plus souvent qu'il n'est écrit, les indices de l'intention du code peuvent être très précieux par la suite.

1voto

Yishai Points 42417

La raison pour laquelle vous avez un avertissement du compilateur lorsque vous utilisez List au lieu de List<Object> c'est que lorsque vous avez un List le compilateur ne sait pas de quel type de liste il s'agit, donc alors que vous pourriez la traiter comme une List<Object> le compilateur ne peut pas s'assurer qu'à un autre moment dans le code, il n'a pas été défini pour faire référence à un fichier de type List<String> et la sécurité de type des génériques ne peut pas être vérifiée. C'est vraiment l'avertissement du compilateur ici - il dit qu'il ne peut pas aider à assurer la sécurité de type des génériques, et cela n'arrivera pas non plus au moment de l'exécution (jusqu'à ce qu'à un moment ultérieur il y ait un cast réel dans le code).

0voto

Sean Owen Points 36577

Pour les besoins ici, on pourrait dire que c'est la même chose. Mais on peut supposer que vous ne remplissez presque jamais un fichier List avec une pure instance de Object . Ils sont String ou autre. Dans cet exemple, List<Object> utilise techniquement des génériques mais n'en tire pas vraiment parti. Ainsi, il perd la vérification de type à la compilation des génériques.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X