Pourquoi ImmutableList de Guava a-t-il autant de méthodes () surchargées?

Je regardais juste ImmutableList de Guava 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  ImmutableList of(); static  ImmutableList of(E element); // not even necessary static  ImmutableList of(E... elements); 

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

    Varargs et génériques ne jouent pas bien ensemble. Les méthodes Varargs peuvent provoquer un avertissement avec des arguments génériques, et les surcharges empêchent cet avertissement, sauf dans les rares cas où vous souhaitez append plus de 11 éléments à la liste immuable à l’aide of() .

    Les commentaires dans la source disent:

    Celles-ci vont jusqu’à onze. Après cela, vous obtenez juste le formulaire varargs, et tous les avertissements qui pourraient lui être associés. 🙁

    Notez que l’annotation @SafeVarargs de Java 7 a été ajoutée spécifiquement pour éliminer ce besoin. Une seule méthode of(E...) annotée avec @SafeVarargs pourrait être utilisée et ne donnerait pas d’avertissement avec des arguments génériques.

    Il y a aussi une raison de performance. Chaque invocation d’une méthode varargs provoque une allocation de tableau et une initialisation. 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 surcharger comme ça

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

    conduit à une belle augmentation de la performance dans 95% des cas. Autrement dit, la performance moyenne des cas augmente.

    En plus des autres excellentes réponses, il existe un avantage de performance d’exécution subtil (en plus d’éviter l’allocation de tableau), à savoir que les surcharges à zéro-argument et à un seul argument renvoient des implémentations optimisées pour représenter des listes vides et à instance unique (respectivement).

    Si nous n’avions pas de surcharges de méthodes distinctes pour ces méthodes et si nous n’incluions qu’une seule méthode basée sur varargs, cette méthode ressemblerait à ceci:

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

    Les performances du commutateur (ou si-else vérifie) ne seraient pas mauvaises pour la plupart des appels, mais elles sont toujours inutiles car elles ne peuvent contenir que des surcharges de méthode pour chaque optimisation et le compilateur sait toujours quelle surcharge appeler. Il n’y a pas de fardeau pour le code client, donc c’est facile à gagner.