38 votes

Pourquoi la liste immuable de Guava a-t-elle autant de méthodes () surchargées?

Je regardais juste le ImmutableList goyave et j'ai remarqué que la méthode of() était surchargée 12 fois.

Il me semble que tout ce dont ils avaient besoin était:

 static <E> ImmutableList<E> of();
static <E> ImmutableList<E> of(E element); // not even necessary
static <E> ImmutableList<E> of(E... elements);
 

Quelle est la raison d'avoir autant de variations similaires?

40voto

ColinD Points 48573

Varargs et les génériques ne jouent pas bien ensemble. Varargs méthodes peuvent provoquer un avertissement avec des arguments génériques, et les surcharges éviter cet avertissement, sauf dans les rares cas où vous voulez ajouter plus de 11 points à la liste immuable à l'aide de of().

Les commentaires dans le source de le dire:

Ces aller jusqu'à onze. Après cela, vous obtenez juste le varargs forme, et quelles que soient mises en garde pourrait venir avec elle. :(

Notez que Java 7 @SafeVarargs annotation a été ajoutée spécifiquement pour éliminer le besoin pour ce genre de chose. Un seul of(E...) méthode annotée avec l' @SafeVarargs pourrait être utilisé, et ne serait pas donner des avertissements avec des arguments génériques.

13voto

Rinke Points 993

Il y a aussi une raison de performance. Chaque appel d'une méthode varargs provoque une allocation et une initialisation de tableau. Si vous avez en quelque sorte déterminé que, par exemple, 95% des appels sont avec 3 arguments ou moins et seulement 5% avec 4 ou plus, alors la surcharge comme ceci

 public static <E> ImmutableList<E> of();
public static <E> ImmutableList<E> of( E e );
public static <E> ImmutableList<E> of( E e1, E e2 );
public static <E> ImmutableList<E> of( E e1, E e2, E e3 );
public static <E> ImmutableList<E> of( E e1, E e2, E e3, E... es );
 

conduit à une belle augmentation des performances dans 95% des cas. Autrement dit, les performances moyennes des cas augmentent.

4voto

Andrew McNamee Points 645

En plus des autres grandes réponses ici, il y a une subtile les performances d'exécution avantage (en plus d'éviter l'allocation de tableau), qui est que le zéro-arg et unique-arg surcharges retour des implémentations optimisées pour la représentation vide et un seul cas de listes (respectivement).

Si nous n'avions pas de méthode distincte des surcharges de ces et ne comprenaient un seul varargs méthode de base, alors que la méthode devrait ressembler à quelque chose comme ceci:

public static <E> ImmutableList<E> of(E... es) {
    switch (es.length) {
      case 0:
        return emptyImmutableList();
      case 1:
        return singletonImmutableList(es[0]);
      default:
        return defaultImmutableList(es);
    }
}

Le fonctionnement de l'interrupteur de cas (ou si-sinon vérifie) ne serait pas mauvais pour la plupart des appels, mais il est encore inutile puisque juste avoir surcharges de méthode pour chaque optimisation, et le compilateur sait toujours qui surcharge à l'appel. Il n'y a pas de fardeau placé sur le code du client, c'est donc une victoire facile.

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