2010-05-20 4 views
5

Naviguer dans les bibliothèques Guava j'ai vu cette signature bizarre sur une méthode readlines de la classe Fichiers:type Java bizarre de retour générique

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

Je sais un peu de médicaments génériques en Java, mais cela me déconcerté.

Que signifie le double T ici? Et pourquoi est le premier dans les parenthèses inclinées?

MISE À JOUR: Merci pour les réponses. Je ne comprends toujours pas pourquoi je devrais utiliser un T à l'intérieur des supports. Pourquoi, par exemple ne peut-il être juste:

public static <> T readLines() 

ou

pulibc static <K> T readLines() 

Ou la syntaxe java Dictate que la même lettre doit être utilisé?

maintenant this est encore wierder:

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

comment une méthode ont un type générique-retour et être vide?

+0

Le T entre chevrons n'est PAS le type de retour; c'est le paramètre de type pour la méthode. –

+0

Notez que s'il n'y avait pas dans les signatures ci-dessus, le compilateur s'attendrait naturellement à trouver "class T {...}" défini quelque part. Quelque chose doit informer le compilateur que vous aimeriez qu'il y ait un paramètre de type * appelé T. Et c'est ainsi. –

Répondre

3

Je ne comprends toujours pas pourquoi je devrais utiliser un T à l'intérieur des supports. Pourquoi, par exemple ne peut-il être juste:

public static <> T readLines() 

ou

public static <K> T readLines() 

Ou la syntaxe java Dictate que la même lettre doit être utilisé?

Le <T> ou <K> est le paramètre de type. Si vous écrivez <K> T, alors le T n'est pas un paramètre de type - plutôt, vous utilisez le class T spécifique. Cela ne fonctionnera pas si vous n'avez pas une classe littéralement nommée T dans la portée.

Maintenant, ce qui est encore wierder:

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

comment une méthode ont un type générique-retour et être vide?

Ce n'est pas le cas; le <T> n'est pas un "type de retour générique", c'est juste le paramètre type de la méthode. Vous dites que la méthode est générique, et T est le paramètre de type. Le type de retour de la méthode est void.

+0

C'est la phrase que je cherchais: "Vous dites que la méthode est générique, et T est le paramètre de type." Merci! – drozzy

7

Le premier T à l'intérieur des chevrons signifie que la méthode elle-même est générique. Le deuxième T est le type de retour. T peut être n'importe quel type dans ses limites. Dans ce cas, T n'a pas de limite.

T sera déterminé sur le site d'appel, et dans ce cas, déduit du paramètre LineProcessor <T>.

9

Il est une méthode générique - le T est appelé un paramètre de type et peut représenter tout type. Donc, si j'ai une méthode avec cette signature:

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

je peux l'appeler sur un tableau, et il retournera un seul objet du même type. Si je lui passe un tableau de chaînes, je récupèrerai une chaîne, et ainsi de suite. Plus d'informations in the Sun tutorials for "generic methods".

Edit: En réponse à votre question mise à jour, gardez à l'esprit que le premier <T>n'est pas partie du type de retour: il est juste un indicateur qui T est un paramètre de type. Regardez donc l'exemple que vous avez cité:

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

Cela signifie juste que fromArrayToCollection acceptera tout tableau et une collection, mais qu'ils doivent être un tableau et collection du même type. Donc, vous pouvez passer un String[] et un Collection<String>, ou un Integer[] et un Collection<Integer>, mais pas un String[] et un Collection<Integer>. Peu importe le type que vous mettez pour T, la méthode ne retourne rien.

+0

Merci, voir mise à jour à ma question – drozzy

0

Ceci est une méthode générique.

Actuellement, il y a trois Ts, le troisième sur LineProcessor<T> spécifie T lorsque vous utilisez la méthode.

3

Au lieu d'être générique au niveau de la classe, seule la méthode readLines utilise des génériques.

  • Le premier <T> déclare les types génériques utilisés par la méthode
  • Le T suivant est le type de retour.

Le premier utilise la même syntaxe qu'une classe générique pour déclarer les types génériques. Au lieu de cela, vous pouvez écrire

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

Cela rendrait toutefois toutes les instances de la classe générique.

Exemple étendu:

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

La méthode ajoute un élément donné à une liste et retourne la liste.
La méthode utilise deux types génériques un pour les éléments de la liste et un pour la liste elle-même.
Les noms utilisés n'ont rien de spécial, utiliser un T pour un type générique est comme utiliser i pour un entier.

  • ElementType est le nom utilisé pour le type générique des éléments (un nom de variable valide/identifiant peut être utilisé)
  • ListType est le nom de la liste générique de type, les classes utilisées doivent étendre/implémenter la liste pour ElementType.

L'exemple appelle la méthode avec:

  • ElementType = Chaîne
  • ListType = ArrayList

qui entraînerait
public static ArrayList<String> add(ArrayList<String> list, String elem)

fin ballonnement :-)

+0

Merci, cela rend plus clair ... mais pourquoi dois-je utiliser une lettre "T" à l'intérieur des parenthèses, par opposition à, disons, lettre "K" ou "B" ou aucun à tous (c'est-à-dire juste des parenthèses vides). – drozzy

+0

La lettre T est seulement un nom, les noms entre < and > déclarent seulement des noms pour les types génériques utilisés. Vous pouvez déclarer une méthode avec 3 types génériques tels que public static ExtraType someMethod (TypeA var1, AnOtherTypeB var2, ExtraType var3). – josefx

Questions connexes