При просматривании библиотек 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) {
как метод может иметь тип универсального возврата и быть пустым?
Я до сих пор не понимаю, почему я должен использовать букву T в скобках. Почему, например, это не может быть просто:
public static <> T readLines ()
или
общедоступный статический
T readLines () Или синтаксис java требует использования ОДНОЙ буквы?
или
является параметром типа. Если вы пишете
, то T не является параметром типа - скорее, вы используете конкретный класс T
. Это не сработает, если у вас нет класса с буквальным названием T
в области видимости.
Теперь это еще более странно:
static
void fromArrayToCollection (T [] a, Collection c) { как метод может иметь тип универсального возврата и быть недействительным?
Нет;
не является «универсальным возвращаемым типом», это просто параметр типа для метода. Вы говорите, что метод является универсальным, а T
является параметром типа. Тип возврата метода - void
.
Вместо того, чтобы быть универсальным на уровне класса, только метод readLines использует универсальные шаблоны.
объявляет универсальные типы, используемые методом Первый использует тот же синтаксис, что и универсальный класс, для объявления универсальных типов. Вместо этого вы можете написать
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 для целого числа.
В примере вызывается метод с:
, что приведет к добавлению
общедоступного статического ArrayList
Раздутый конец: -)
Это универсальный метод - 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
, метод ничего не возвращает.
Первая буква T в угловых скобках означает, что сам метод является универсальным. Второй T - это возвращаемый тип. T может быть любым типом в пределах своих границ. В этом случае T не имеет границ.
T будет определяться на месте вызова, и в этом случае выводится из параметра LineProcessor
Это общий метод.
На самом деле есть три Ts, третий на LineProcessor
указывает T, когда вы используете метод.