Почему ImmutableList в Guava имеет так много перегруженных методов ()? - PullRequest
38 голосов
/ 17 сентября 2010

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

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

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

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

Ответы [ 3 ]

39 голосов
/ 17 сентября 2010

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

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

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

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

13 голосов
/ 16 сентября 2011

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

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

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

4 голосов
/ 01 сентября 2012

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...