Почему у ImmavableList Guava столько перегруженных методов ()?

Я просто смотрел на ImmutableList Guava, и я заметил, что метод of() был перегружен 12 раз.

Мне кажется, что все, что им нужно, было:

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

В чем причина стольких подобных изменений?

Варгары и дженерики не играют хорошо вместе. Методы Varargs могут вызывать предупреждение с помощью общих аргументов, а перегрузки предотвращают это предупреждение, за исключением редкого случая, когда вы хотите добавить более 11 элементов в неизменяемый список, используя of() .

Комментарии в источнике говорят:

Они доходят до одиннадцати. После этого вы просто получите форму varargs, и любые предупреждения могут появиться вместе с ней. 🙁

Обратите внимание, что аннотация JavaS @SafeVarargs была добавлена ​​специально для устранения необходимости в подобных вещах . Один of(E...) аннотированный с помощью @SafeVarargs может быть использован и не будет давать предупреждения с помощью общих аргументов.

Существует также причина в производительности. Каждый вызов метода varargs вызывает распределение и инициализацию массива. Если вы каким-то образом определили, что, например, 95% вызовов имеют 3 или менее аргумента и только 5% с 4 или более, то перегрузка как это

 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 ); 

приводит к хорошему повышению производительности в 95% случаев. Иными словами, средняя производительность приложения увеличивается.

В дополнение к другим замечательным ответам здесь есть небольшое преимущество производительности во время выполнения (в дополнение к тому, чтобы избежать распределения массива), а это то, что переопределения с нулевым аргументом и одним-arg возвращают реализации, оптимизированные для представления пустых и одиночных списков (соответственно).

Если бы у нас не было отдельных перегрузок методов для них и включался только один метод на основе varargs, тогда этот метод выглядел бы примерно так:

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

Производительность коммутатора (или проверки if-else) не будет плохой для большинства вызовов, но она по-прежнему не нужна, поскольку может быть просто перегрузка метода для каждой оптимизации, и компилятор всегда знает, какую перегрузку нужно вызывать. На клиентский код нет бремени, так что это легкая победа.

  • Перегрузка Java-методом + двойная отправка
  • перегрузка метода vs необязательный параметр в C # 4.0
  • Неоднозначный вызов Varargs Java
  • Лямбда-выражение и метод перегружают сомнения
  • Java - почему нет перегрузки метода на основе возвращаемого типа?
  • Конфликт перегруженных методов с дополнительными параметрами
  • Перегрузка метода для нулевого аргумента
  • Почему String.valueOf (null) вызывает исключение NullPointerException?
  • Почему тип-продвижение имеет приоритет над varargs для перегруженных методов
  • Почему «избегать перегрузки метода»?
  • Почему перегрузка метода не допускается в WCF?
  • Давайте будем гением компьютера.