2010-05-20 5 views
5

Листая Guava библиотеки я увидел эту странную подпись на методе readLines из файлов класса:Java странно общий тип возвращаемого

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

Я знаю немного о воспроизведенных в Java, но это озадачило меня.

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

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

public static <> T readLines() 

или

pulibc static <K> T readLines() 

Или диктуют, что такое же письмо необходимо использовать синтаксис Java?

Теперь this даже wierder:

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

как метод может иметь тип общий обратный и аннулируются?

+0

T в угловых скобках НЕ является типом возврата; это параметр типа для метода. –

+0

Обратите внимание, что если в приведенных выше подписях не было , компилятор, естественно, ожидал бы найти «класс T {...}», определенный где-то. Что-то должно сообщить компилятору, что вы хотите, чтобы там был параметр * type *, называемый T. И это так. –

ответ

3

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

public static <> T readLines() 

или

public static <K> T readLines() 

Или диктуют, что такое же письмо необходимо использовать синтаксис Java?

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

Теперь это даже wierder:

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

как метод может иметь тип общий обратный и аннулируются?

Это не так; <T> не является «общим типом возврата», это просто параметр типа для метода. Вы говорите, что метод является общим, а T - это параметр типа. Возвращаемый тип метода: void.

+0

Это предложение, которое я искал: «Вы говорите, что метод является общим, а T является параметром типа». Благодаря! – drozzy

7

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

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

9

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

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

Я могу назвать его на любом массиве, и он будет возвращать один объект того же типа. Если я передам массив String, я верну String и так далее. Более подробная информация in the Sun tutorials for "generic methods".

Edit: В ответ на ваш обновленный вопрос, иметь в виду, что первый <T>не часть возвращаемого типа: это просто показатель того, что T является параметром типа. Так что смотрите на примере вы цитируемого:

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

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

+0

Спасибо, см. Обновление к моему вопросу – drozzy

0

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

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

3

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

  • Первый <T> объявляет общие типы, используемые методом
  • Ниже Т тип возврата.

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

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

Это однако сделало бы все экземпляры класса generic.

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

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 = Строка
  • ListType = ArrayList

что привело бы к
public static ArrayList<String> add(ArrayList<String> list, String elem)

Bloat конца :-)

+0

Спасибо, это делает его более ясным ... но почему я должен использовать букву «Т» внутри скобок, в отличие от, скажем, буквы «К» или «В», или нет в все (т.е. просто пустые скобки). – drozzy

+0

Буква T - это только имя, имена между < and > только объявляют имена для используемых типовых типов. Вы можете объявить метод с тремя типами общего типа, такими как public static ExtraType someMethod (TypeA var1, AnOtherTypeB var2, ExtraType var3). – josefx

Смежные вопросы