2 votes

Générique avec limites vs. interface avec types génériques

Considérons le code suivant

/**
 * Generic method with bounds
 */
public static <T> int countGreaterThan(Comparable<T>[] anArray,
        T elem) {
    int count = 0;
    for (Comparable<T> e : anArray)
        if (e.compareTo(elem) > 0)
            ++count;
    return count;
}
/**
 * Alternative to above
 */
public static <T extends Comparable<T>> int countGreaterThan(T[] anArray, T elem) {
    int count = 0;
    for (T e : anArray)
        if (e.compareTo(elem) > 0)
            ++count;
    return count;
}

Il semble que les deux soient fonctionnellement identiques. Cependant, elles peuvent apparaître dans la même classe en se surchargeant mutuellement. Lorsque j'utilise le code suivant, il semble que la deuxième méthode soit invoquée. Sans la deuxième méthode de surcharge, c'est la première méthode qui est invoquée. Quelqu'un peut-il fournir une explication approfondie ?

    Integer[] array = new Integer[10];
    for (int i = 0; i < array.length; ++i)
        array[i] = i;

    System.out.println("Count > 5 = " + countGreaterThan(array, 5));

2voto

Carlo Pellegrini Points 2845

Eh bien, ce n'est pas un effacement complet.

La première méthode

<T> int countGreaterThan(Comparable<T>[] anArray,T elem)

fonctionne sur un tableau de Comparable<T> mais n'exige pas que elem est également Comparable .

Vous pouvez le vérifier sur :

static class Y {
   int val;
   public Y(int val){
      this.val=val;
   }
} 

static class W extends Y implements Comparable<Y>{
   public W(int val){
      super(val);
   }
   public int compareTo(Y o){
      return this.val-o.val;
   } 
}

W[] array = new W[10];
for (int i = 0; i < array.length; ++i)
    array[i] = new W(i);

System.out.println("Count > 5 = " + countGreaterThan(array, new Y(5)));       

La première méthode sera appelée.

1voto

Sean Owen Points 36577

(Ils peuvent apparaître dans la même classe puisqu'ils n'ont pas la même rature. La première a un premier argument de type Comparable[] et le second de type Object[] .)

Les deux méthodes peuvent s'appliquer ; en Java, la méthode à appeler est déterminée à la compilation et est toujours la surcharge la plus spécifique basée sur le type de référence de l'argument.

Carlo Pellegrini a raison de dire que le premier serait appelé pour n'importe quel vieux Comparable . De plus grands experts me corrigeront peut-être, mais je suis à peu près sûr que cela est dû à la mise en boîte. L'appel dans votre exemple lie Integer[] a T[] d'abord, et ensuite cela induit la mise en boîte de int a T qui est maintenant réifié comme Integer . Dans le cas de son exemple Y il ne peut correspondre qu'au premier.

0voto

JB Nizet Points 250258

C'est parce qu'en Java, une Integer[] est également un Comparable[] . Si vous aviez la même méthode avec une liste au lieu d'un tableau comme arguments, cela ne fonctionnerait pas de la même manière, car un List<Integer> n'est pas un List<Comparable> . Ainsi, seule la deuxième version accepterait un List<Integer> comme argument.

Les collections sont plus sûres au niveau des types et fonctionnent mieux avec les génériques que les tableaux. Vous devriez les préférer aux tableaux en général.

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