109 votes

Qu'est-ce que la syntaxe < ? super T> ?

J'ai du mal à comprendre la syntaxe suivante :

public class SortedList< T extends Comparable< ? super T> > extends LinkedList< T >

Je vois que la classe SortedList étend LinkedList. Mais je ne sais pas ce que

T extends Comparable< ? super T>

signifie.

D'après ce que j'ai compris jusqu'ici, le type T doit être un type qui implémente Comparable... mais qu'est-ce que c'est ? < ? super T > ?

113voto

Yishai Points 42417

Super dans Generics est l'opposé de extends. Au lieu de dire que le type générique du comparable doit être une sous-classe de T, il dit qu'il doit être une super-classe de T. La distinction est importante car extends vous dit ce que vous pouvez obtenir d'une classe (vous obtenez au moins ceci, peut-être une sous-classe). super vous dit ce que vous pouvez mettre dans la classe (au plus ceci, peut-être une super-classe).

Dans ce cas précis, ce qu'elle dit, c'est que le type doit implémenter des comparables de lui-même ou de sa superclasse. Prenons l'exemple de java.util.Date. Il implémente Comparable<Date> . Mais qu'en est-il de java.sql.Date ? Elle implémente Comparable<java.util.Date> également.

Sans la super signature, SortedList ne pourrait pas accepter le type java.sql.Date, car elle n'implémente pas un Comparable d'elle-même, mais plutôt d'une super classe d'elle-même.

99voto

polygenelubricants Points 136838

C'est un joker à limite inférieure.

JLS 4.5.1 Arguments de type et caractères génériques

Les caractères génériques sont utiles dans les situations où seule une connaissance partielle du paramètre de type est requise. [...] Une limite supérieure est signifiée par la syntaxe :

? extends B

B est la limite supérieure. [...] il est permis de déclarer des limites inférieures sur un joker, en utilisant la syntaxe :

? super B

B est une borne inférieure.

A List<? super Integer> par exemple, comprend List<Integer> , List<Number> y List<Object> .

Les caractères génériques sont utilisés pour rendre les génériques plus puissants et plus flexibles ; les limites sont utilisées pour maintenir la sécurité des types.

Voir aussi


Pour ce qui est de l'utilité de cet outil dans <T extends Comparable<? super T>> c'est quand vous avez quelque chose comme Cat extends Animal implements Comparable<Animal> .

Regardez la signature de Collections.sort

public static <T extends Comparable<? super T>> void sort(List<T> list)

Par conséquent, avec un List<Cat> listOfCat vous pouvez maintenant Collections.sort(listOfCat) .

S'il avait été déclaré comme suit :

public static <T extends Comparable<T>> void sort(List<T> list)

alors il faudrait que tu aies Cat implements Comparable<Cat> à utiliser sort . En utilisant le ? super T joker délimité, Collections.sort devient plus flexible.

Voir aussi

  • Effective Java 2e édition, point 28 : utiliser les caractères génériques délimités pour accroître la flexibilité de l'API.
    • Aussi, le principe PECS : "producteur extends consommateur super "

15voto

Petar Minchev Points 24864

Cela signifie que T doit mettre en œuvre Comparable<T itself or one of T's superclasses> Le sens est que, parce que SortedList est trié, il doit savoir comment comparer deux classes de ses génériques T paramètre. C'est pourquoi T doit mettre en œuvre Comparable<T itself or one of T's superclasses>

6voto

John Smith Points 196

Cela signifie que le type T doit mettre en œuvre Comparable de T ou l'une de ses super classes.

Par exemple, si A étend B si vous voulez utiliser SortedList<A> , A doit mettre en œuvre Comparable<A> o Comparable<B> ou en fait juste Comparable .

Cela permet à la liste des A peuvent être construits avec n'importe quel comparateur valide.

4voto

Epitaph Points 1200

Prenons l'exemple suivant :

  1. Utilisation d'un paramètre de type défini dans la déclaration de la classe

    public class ArrayList extends AbstractList ... {
    public boolean add(E o) // Vous pouvez utiliser le "E" ici UNIQUEMENT parce qu'il a déjà été défini comme faisant partie de la classe.

  2. Utilisation d'un paramètre de type qui n'a PAS été défini dans la déclaration de la classe

    public <T extends Animal> void takeThing(ArrayList<T> list)
                                                // Here we can use <T> because we declared "T" earlier in the method declaration                  

    Si la classe elle-même n'utilise pas de paramètre de type, vous pouvez toujours en spécifier un pour une méthode, en le déclarant dans un espace vraiment inhabituel (mais disponible) - avant le type de retour. Cette méthode dit que T peut être "n'importe quel type d'animal".

NOTE :

public <T extends Animal> void takeThing(ArrayList<T> list)             

is NOT same as              

public void takeThing(ArrayList<Animal> list)

Les deux sont légaux, mais ils sont différents. La première indique que vous pouvez passer un objet ArrayList instancié en tant qu'Animal ou tout sous-type d'Animal comme ArrayList, ArrayList ou ArrayList. Mais, vous ne pouvez passer que ArrayList dans la seconde, et PAS n'importe lequel des sous-types.

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