T
. Proposons une première implémentation.
Exemple 24. Première et mauvaise implémentation de
getFirst(T t)
public class ArrayUtils { public static <T> T getFirst(T[] arrayOfT) { T min = arrayOfT[0] ; for (T t : arrayOfT) { if (t instanceof Comparable) { Comparable c = (Comparable)t ; if (c.compareTo(min) < 0) { min = t ; } } } return min ; } }
t
est bien comparable, et à utiliser un mode dégradé qui n'a pas de sens. Tout d'abord notre méthode n'a de sens que si
t
est de type
Comparable
.
T
en étend un autre, comme nous pouvons le voir sur cet exemple corrigé.
Exemple 25. Seconde implémentation de
getFirst(T t)
public class ArrayUtils { public static <T extends Comparable<T>> T getFirst(T[] arrayOfT) { T min = arrayOfT[0] ; for (T t : arrayOfT) { if (t.compareTo(min) < 0) { min = t ; } } return min ; } }
T
peut être une classe ou une interface, de même que le type étendu. Le
extends
utilisé ici signifie juste que le type proposé doit
être de type
Comparable
. Le sens de ce
extends
n'est donc pas exactement le même que le
extends
utilisé pour signaler qu'une classe en étend une autre.
On peut d'ailleurs imposer des contraintes multiples sur un type générique, comme dans l'exemple suivant.
Exemple 26. Contraintes multiples sur un type générique
public class ArrayUtils { public static <T extends Comparable & Serializable> T getFirst(T[] arrayOfT) { ... } }
T
soit à la fois
Comparable
et
Serializable
. Il existe des limites à la liste des types que l'on peut préciser :