Java странный универсальный тип возврата

При просматривании библиотек Guava я видел эту странную подпись на readLines методе от класса Файлов:

public static  T readLines(File file,
                          Charset charset,
                          LineProcessor callback)

Я знаю немного о дженериках в Java, но это экранировало меня.

Что делает двойной T, средний здесь? И почему первый в угловых скобках?

ОБНОВЛЕНИЕ: Спасибо за ответы. Я все еще не ясен относительно того, почему я должен использовать T в скобках. Почему, например, не может он просто быть:

 public static <> T readLines()

или

 pulibc static  T readLines()

Или синтаксис Java диктует, что ТА ЖЕ буква должна использоваться?

Теперь это еще более странно:

static  void fromArrayToCollection(T[] a, Collection c) {

как метод может иметь тип универсального возврата и быть пустым?

5
задан skaffman 9 June 2010 в 20:41
поделиться

5 ответов

Я до сих пор не понимаю, почему я должен использовать букву T в скобках. Почему, например, это не может быть просто:

  public static <> T readLines ()

или

  общедоступный статический  T readLines ()

Или синтаксис java требует использования ОДНОЙ буквы?

или является параметром типа. Если вы пишете T , то T не является параметром типа - скорее, вы используете конкретный класс T . Это не сработает, если у вас нет класса с буквальным названием T в области видимости.

Теперь это еще более странно:

 static  void fromArrayToCollection (T [] a, Collection  c) {

как метод может иметь тип универсального возврата и быть недействительным?

Нет; не является «универсальным возвращаемым типом», это просто параметр типа для метода. Вы говорите, что метод является универсальным, а T является параметром типа. Тип возврата метода - void .

3
ответ дан 18 December 2019 в 07:08
поделиться

Вместо того, чтобы быть универсальным на уровне класса, только метод readLines использует универсальные шаблоны.

  • Первый объявляет универсальные типы, используемые методом
  • Следующий T - это возвращаемый тип.

Первый использует тот же синтаксис, что и универсальный класс, для объявления универсальных типов. Вместо этого вы можете написать

class Generic <T> 
{
public static T readLines(File file,
                          Charset charset,
                          LineProcessor<T> callback)
}

Это, однако, сделает все экземпляры класса универсальными.

Расширенный пример:

public static <ElementType,ListType extends List<ElementType>> ListType add(ListType list,ElementType elem)
{
   list.add(elem);
   return list;
}
ArrayList<String> = add(add(new ArrayList<String>(),"Hello"),"World");

Метод добавляет заданный элемент в список и возвращает список.
В этом методе используются два общих типа: один для элементов списка, а другой - для самого списка.
В используемых именах нет ничего особенного, использование T для универсального типа похоже на использование i для целого числа.

  • ElementType - это имя, используемое для универсального типа элементов (можно использовать любое допустимое имя / идентификатор переменной).
  • ListType - это имя для универсального типа списка, используемые классы должны расширять / реализовывать List для ElementType.

В примере вызывается метод с:

  • ElementType = String
  • ListType = ArrayList

, что приведет к добавлению
общедоступного статического ArrayList (список ArrayList , элемент String)

Раздутый конец: -)

3
ответ дан 18 December 2019 в 07:08
поделиться

Это универсальный метод - T называется параметром типа и может представлять любой тип. Итак, если у меня есть метод с такой сигнатурой:

public <T> T foo(T[] bar)

, я могу вызвать его для любого массива, и он вернет единственный объект того же типа. Если я передам ему массив String, я верну String и так далее. Дополнительную информацию можно найти в учебниках Sun по «универсальным методам».

Изменить: В ответ на ваш обновленный вопрос имейте в виду, что первая не является частью возвращаемого типа: это просто индикатор того, что T - параметр типа. Итак, посмотрите на приведенный вами пример:

static <T> void fromArrayToCollection(T[] a, Collection<T> c)

Это просто означает, что fromArrayToCollection будет принимать любой массив и любую коллекцию, но , что они должны быть массивом и коллекцией одного типа. Таким образом, вы можете передать String [] и Collection или Integer [] и Collection , но не String [] и Collection . Независимо от того, какой тип вы указали для T , метод ничего не возвращает.

9
ответ дан 18 December 2019 в 07:08
поделиться

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

T будет определяться на месте вызова, и в этом случае выводится из параметра LineProcessor .

7
ответ дан 18 December 2019 в 07:08
поделиться

Это общий метод.

На самом деле есть три Ts, третий на LineProcessor указывает T, когда вы используете метод.

0
ответ дан 18 December 2019 в 07:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: