200 votes

Différence entre liste, liste <?> , Liste <T> , Liste <E> , et liste <Object>

Quelles sont les différences entre List, List<?>, List<T>, List<E>, et List<Object>?

Maintenant, je n'ai pas aveuglément poser cette question, donc merci de ne pas fermer ce fil. Permettez-moi d'abord introduire le code de base:

private static List<String> names = new ArrayList<String>();
static {
    names.add("Tom");
    names.add("Peter");
    names.add("Michael");
    names.add("Johnson");
    names.add("Vlissides");
}

public static void test(List<String> set){
    System.out.println(set);
}
public static void main(String args[]){
    test(names);
}

Je comprends que:

1.List: est une crue de type, donc pas typesafe. Il ne fera que générer une erreur d'exécution lors de la coulée est mauvais. Nous voulons une erreur de compilation quand le plâtre est mauvais. Recommandé de ne pas utiliser.

2.List<?>: est une surabondance de génériques. Mais vous ne savez pas ce que c'est? Donc si je change le test méthode de

public static void test(List<?> set){
    System.out.println(set);
}

il fonctionne encore bien. Si vous pouvez expliquer l'utilisation de cette application, je vous en serais très reconnaissante.

EDIT: Si je fais ceci:

public static void test(List<?> set){
    set.add(new Long(2)); //--> Error
    set.add("2");    //--> Error
    System.out.println(set);
}

mais si je change test de cette:

public static void test(List<String> set){
    set.add(new Long(2)); //--> Error
    set.add("2");    //--> Work
    System.out.println(set);
}

3.List<T>:

public static void test(List<T> set){   //T cannot be resolved
    System.out.println(set);
}

Je suppose que je ne comprends pas cette syntaxe. J'ai vu quelque chose comme ça, et ça fonctionne:

public <T> T[] toArray(T[] a){
    return a;   
}

Veuillez l'expliquer moi s'il vous plaît? Parfois, je vois des <T>ou <E>ou <U>, <T,E>. Sont-ils tous les mêmes ou qu'elles ne représentent quelque chose de différent?

4.List<Object>

public static void test(List<Object> set){
    System.out.println(set);
}

Puis j'ai eu l'erreur The method test(List<Object>) is not application for the argument List<String> pour le code ci-dessous. Je suis confus. J'ai pensé String a un sous-ensemble de l' Object?

public static void main(String args[]){
    test(names); 
}

EDIT: Si j'essaie ce

test((List<Object>)names);

puis j'ai eu l' Cannot cast from List<String> to List<Object>

84voto

Kaj Points 6802

1) Corriger

2) Vous pouvez penser que l'on en "lecture seule" de la liste, où vous n'avez pas de soins sur le type des éléments.Pourraient par exemple être utilisés par une méthode qui retourne la longueur de la liste.

3) T, E et U sont les mêmes, mais les gens ont tendance à utiliser, par exemple, T pour type, E pour l'Élément, V pour la valeur et K de clé. La méthode qui compile dit qu'il parlent d'un tableau d'un certain type, et retourne un tableau du même type.

4) Vous ne pouvez pas mélanger les oranges et les pommes. Vous serez en mesure d'ajouter un Objet à votre liste de chaînes, si vous pouvez passer une liste de chaînes à une méthode qui attend des listes d'objets. (Et pas tous les objets sont des chaînes de caractères)

27voto

Farshid Zaker Points 1081

Pour la dernière partie: Bien que String soit un sous-ensemble de Object, mais List <String> n'est pas hérité de List <Object>.

20voto

Ted Hopp Points 122617

La notation List<?> signifie "une liste de tout". Depuis que le code en test fonctionne pour n'importe quel type d'objet dans la liste, cela fonctionne comme une méthode officielle de paramètre.

À l'aide d'un paramètre de type (comme dans votre point 3), il faut que le paramètre du type d'être déclarée. La syntaxe Java pour qui est de mettre <T> devant de la fonction. C'est exactement analogue à la déclaration officielle des noms de paramètre à une méthode avant d'utiliser les noms dans le corps de la méthode.

Concernant l' List<Object> ne pas accepter une List<String>, qui fait sens parce qu'un String n'est Object; c'est une sous-classe de la Object. La solution est de déclarer public static void test(List<? extends Object> set) .... Mais alors, l' extends Object redondantes, car chaque classe, directement ou indirectement, s'étend Object.

14voto

Peter Points 4694

La raison pour laquelle vous ne pouvez lancer List<String> de List<Object> , c'est qu'il vous permettra de violer les contraintes de l' List<String>.

Pensez à le scénario suivant: Si j'ai un List<String>, elle est censée ne contenir que des objets de type String. (Qui est une final de la classe)

Si je peux l'appliquer à un List<Object>, alors que me permet d'ajouter Object à la liste, violant ainsi le contrat initial d' List<String>.

Ainsi, en général, si la classe C hérite de la classe P, on ne peut pas dire qu' GenericType<C> hérite également d' GenericType<P>.

N. B. j'ai déjà commenté sur ce dans une réponse précédente, mais a voulu étendre sur elle.

5voto

Je conseillerais de lire des casse-tête Java. Cela explique assez bien l'héritage, les génériques, les abstractions et les caractères génériques dans les déclarations. http://www.javapuzzlers.com/

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