2010-05-20 19 views
5

Navegación a través de las bibliotecas Guava vi esta firma raro en un método de la clase readlines Archivos:Java Tipo extraño retorno genérica

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

sé un poco acerca de los genéricos en Java, pero esto me desconcertó.

¿Qué significa la doble T aquí? ¿Y por qué el primero está en paréntesis angulares?

ACTUALIZACIÓN: Gracias por las respuestas. Todavía no tengo claro por qué debería usar una T dentro de los corchetes. ¿Por qué, por ejemplo, no puede ser sólo:

public static <> T readLines() 

o

pulibc static <K> T readLines() 

¿O es que dictan que la misma letra debe ser utilizado la sintaxis de Java?

Ahora this es aún wierder:

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

¿cómo puede un método tienen un tipo genérico de retención y se anularán?

+0

La T en paréntesis angulares NO es el tipo de retorno; es el parámetro de tipo para el método. –

+0

Tenga en cuenta que si no hubiera en las firmas anteriores, el compilador esperaría encontrar "clase T {...}" en alguna parte. Algo tiene que informarle al compilador que le gustaría que haya un * parámetro de tipo * llamado T. Y este es el camino. –

Respuesta

3

Todavía no tengo claro por qué debería usar una T dentro de los corchetes. ¿Por qué, por ejemplo, no puede ser sólo:

public static <> T readLines() 

o

public static <K> T readLines() 

¿O es que dictan que la misma letra debe ser utilizado la sintaxis de Java?

El <T> o <K> es el parámetro de tipo. Si escribe <K> T, entonces la T no es un parámetro de tipo, sino que está utilizando el class T específico. Esto no funcionará si no tiene una clase que se llame literalmente T en el alcance.

Ahora bien, esto es aún wierder:

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

¿cómo puede un método tienen un tipo genérico de retención y se anularán?

No; el <T> no es un "tipo de devolución genérico", es solo el parámetro de tipo del método. Usted dice que el método es genérico y T es el parámetro de tipo. El tipo de devolución del método es void.

+0

Esta es la oración que estaba buscando: "Estás diciendo que el método es genérico y T es el parámetro de tipo". ¡Gracias! – drozzy

7

La primera T dentro de los corchetes angulares significa que el método en sí es genérico. El segundo T es el tipo de devolución. T puede ser cualquier tipo dentro de sus límites. En este caso, T no tiene límites.

T se determinarán en el sitio de la llamada, y en este caso, se deducen del parámetro < LineProcessor T >.

9

Es un método genérico- la T se llama un parámetro de tipo , y pueden representar cualquier tipo. Así que si tengo un método con esta firma:

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

me puede llamar en cualquier matriz, y ha de devolver un objeto del mismo tipo. Si le paso una matriz de cadenas, recuperaré una cadena, y así sucesivamente. Más información in the Sun tutorials for "generic methods".

Editar: En respuesta a su pregunta actualizado, tener en cuenta que la primera <T> no es parte del tipo de retorno: es sólo un indicador de que T es un parámetro de tipo. Así que busque en el ejemplo que citan:

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

Eso sólo significa que fromArrayToCollection aceptará ninguna matriz y cualquier colección, pero que debe ser una matriz y la recogida del mismo tipo. De modo que puede pasar String[] y Collection<String>, o Integer[] y , pero no String[] y Collection<Integer>. No importa qué tipo ingrese para T, el método no devuelve nada.

+0

Gracias, consulte la actualización de mi pregunta – drozzy

0

Este es un método genérico.

En realidad, hay tres Ts, el tercero en LineProcessor<T> especifica T cuando utiliza el método.

3

En lugar de ser genérico a nivel de clase, solo el método readLines usa genéricos.

  • La primera <T> declara los tipos genéricos utilizados por el método
  • La siguiente T es el tipo de retorno.

El primero usa la misma sintaxis que una clase genérica para declarar los tipos genéricos. En su lugar, puede escribir

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

Esto, sin embargo, haría genéricas todas las instancias de la clase.

Ejemplo extendido:

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"); 

El método agrega un determinado elemento a una lista y devuelve la lista.
El método utiliza dos tipos genéricos uno para los elementos de la lista y uno para la lista en sí.
Los nombres utilizados no son nada especial, usar una T para un tipo genérico es como usar i para un entero.

  • ElementType es el nombre usado para la genérica tipo de los elementos (cualquier nombre/identificador de variable válido podría utilizarse)
  • ListType es el nombre para el tipo genérico de lista, las clases utilizadas tienen que extenderse/implementar List para ElementType.

el ejemplo llama al método con:

  • ElementType = cadena
  • ListType = ArrayList

lo que resultaría en
public static ArrayList<String> add(ArrayList<String> list, String elem)

extremo Hinchar :-)

+0

Gracias, esto lo aclara ... pero ¿por qué tengo que usar una letra "T" dentro de los corchetes en lugar de, digamos, la letra "K" o "B" o ninguno en todo (es decir, solo corchetes vacíos). – drozzy

+0

La letra T es solo un nombre, los nombres entre < and > solo declaran nombres para los tipos genéricos utilizados. Podría declarar un método con 3 tipos genéricos como este público static ExtraType someMethod (TypeA var1, AnOtherTypeB var2, ExtraType var3). – josefx

Cuestiones relacionadas