Почему я не могу явно передать аргумент типа универсальному методу Java?

StackOverflow https://stackoverflow.com/questions/24991

  •  09-06-2019
  •  | 
  •  

Вопрос

Я определил функцию Java:

static <T> List<T> createEmptyList() {
    return new ArrayList<T>();
}

Один из способов вызвать это так:

List<Integer> myList = createEmptyList(); // Compiles

Почему я не могу вызвать его, явно передав аргумент универсального типа?:

Object myObject = createEmtpyList<Integer>(); // Doesn't compile. Why?

Я получаю ошибку Illegal start of expression из компилятора.

Это было полезно?

Решение

Если компилятор Java не может самостоятельно определить тип параметра для статического метода, вы всегда можете передать его, используя полное имя метода:Сорт .<Тип> метод();

Object list = Collections.<String> emptyList();

Другие советы

Вы можете, если передать тип в качестве параметра метода.

static <T> List<T> createEmptyList( Class<T> type ) {
  return new ArrayList<T>();
}

@Test
public void createStringList() {
  List<String> stringList = createEmptyList( String.class );
}

Методы не могут быть обобщены таким же образом, как тип, поэтому единственный вариант для метода с динамически типизированным универсальным типом возвращаемого значения — уф, это слишком громко :-) — это передать тип в качестве аргумента.

Если вам нужен действительно отличный FAQ по дженерикам Java, см. часто задаваемые вопросы по дженерикам Анжелики Лангер..

.
.

Следовать за:

В этом контексте не имеет смысла использовать аргумент массива, как в Collection.toArray( T[] ).Единственная причина, по которой здесь используется массив, заключается в том, что один и тот же (предварительно выделенный) массив используется для хранения результатов (если массив достаточно велик, чтобы вместить их все).Это позволяет экономить на постоянном выделении нового массива во время выполнения.

Однако в образовательных целях, если вы хотите использовать типизацию массива, синтаксис очень похож:

static <T> List<T> createEmptyList( T[] array ) {
  return new ArrayList<T>();
}

@Test
public void testThing() {
  List<Integer> integerList = createEmptyList( new Integer[ 1 ] );
}

Прошло довольно много времени с тех пор, как я копался в этих частях Java, но...

Почему вы не можете этого сделать, вероятно, это дизайнерский выбор разработчиков языка.Тем не менее, из-за стирание типа используется в Java, информация об обобщениях в любом случае удаляется во время компиляции, поэтому в вашем примере будет создан точно такой же байт-код, независимо от того, есть ли у вас параметр типа или нет.

@pauldoo Да, ты вполне прав.По моему мнению, это одна из слабых сторон Java-дженериков.

В ответ на Cheekysoft я хотел бы предложить также посмотреть, как это делают сами Java-разработчики, такие как T[] AbstractCollection#toArray(Т[]а).Я думаю, что версия Cheekysofts лучше, но у версии Java есть преимущество знакомости.

Редактировать:Добавлена ​​ссылка.Повторное редактирование:Нашел ошибку в SO :)


Продолжение Cheekysoft:Ну, поскольку это список некоторого типа, который должен быть возвращен, соответствующий пример должен выглядеть примерно так:

static <T> List<T> createEmptyList( List<T> a ) {
  return new ArrayList<T>();
}

Но да, передача объекта класса явно лучше.Мой единственный аргумент — это знакомство, и в данном случае оно ничего не стоит (на самом деле это плохо).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top