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

голоса
21

Я определил функцию 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компилятора.

Задан 24/08/2008 в 13:03
источник пользователем
На других языках...                            


4 ответов

голоса
30

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

Object list = Collections.<String> emptyList();
Ответил 25/08/2008 в 12:28
источник пользователем

голоса
22

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

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

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

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

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

,
,

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

Это не имело бы смысла в этом контексте , чтобы использовать аргумент массива , как в 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 ] );
}
Ответил 24/08/2008 в 13:21
источник пользователем

голоса
1

Это было некоторое время, так как я вырыл в те части Java, но ...

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

Ответил 24/08/2008 в 13:19
источник пользователем

голоса
0

@pauldoo Да, вы совершенно правы. Это один из недостатков с IMHO Java дженериков.

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

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


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

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

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

Ответил 24/08/2008 в 13:37
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more