2009-03-06 9 views

Répondre

16

Il n'y a pas de différence pratique en termes de ce que vous pouvez faire quand vous en avez un, car le paramètre type n'est utilisé que dans une position "sortie". D'autre part, il y a une grande différence en termes de ce que vous pouvez utiliser comme l'un d'entre eux. Supposons que vous ayez un Enumeration<JarEntry> - vous ne pouvez pas passer cela à une méthode qui a pris Enumeration<ZipEntry> comme l'un de ses arguments. Vous pouvez passer à une méthode prenant Enumeration<? extends ZipEntry> cependant.

C'est plus intéressant quand vous avez un type qui utilise le paramètre type dans les deux positions d'entrée et de sortie - List<T> étant l'exemple le plus évident. Voici trois exemples de méthodes avec des variations sur un paramètre. Dans chaque cas, nous allons essayer d'obtenir un élément de la liste et en ajouter un autre.

// Very strict - only a genuine List<T> will do 
public void Foo(List<T> list) 
{ 
    T element = list.get(0); // Valid 
    list.add(element); // Valid 
} 

// Lax in one way: allows any List that's a List of a type 
// derived from T. 
public void Foo(List<? extends T> list) 
{ 
    T element = list.get(0); // Valid 
    // Invalid - this could be a list of a different type. 
    // We don't want to add an Object to a List<String> 
    list.add(element); 
} 

// Lax in the other way: allows any List that's a List of a type 
// upwards in T's inheritance hierarchy 
public void Foo(List<? super T> list) 
{ 
    // Invalid - we could be asking a List<Object> for a String. 
    T element = list.get(0); 
    // Valid (assuming we get the element from somewhere) 
    // the list must accept a new element of type T 
    list.add(element); 
} 

Pour plus de détails, lisez:

+0

Une classe ZipEntrySomme JarEntry (la raison pour laquelle ZipFile.entries utilise un caractère générique)? –

+0

Merci Tom - va éditer ma réponse :) –

4

Oui, directement à partir de l'un des sun generics tutorials:

Ici, Shape est une classe abstraite avec trois sous-classes: Circle, Rectangle, et Triangle.

public void draw(List<Shape> shape) { 
    for(Shape s: shape) { 
    s.draw(this); 
    } 
} 

Il convient de noter que le tirage au sort() méthode ne peut être appelée sur les listes de forme et ne peut pas être appelée sur une liste du Cercle, Rectangle et Triangle pour exemple. Afin d'avoir la méthode accepter toute sorte de forme, il devrait être écrit: Maintenant que vous avez

public void draw(List<? extends Shape> shape) { 
    // rest of the code is the same 
} 
+0

C'est la deuxième fois cette semaine Jon Skeet a obtenu une réponse juste avant moi. Je propose que nous nous référons à cela comme Skeeting. – GaryF

+0

sonne bien. quel serait le passé? Sket? "Jon Skeet esquisse encore!" :) – Epaga

+0

http://stackoverflow.com/questions/305223/jon-skeet-facts/317486#317486 –

0

juste allé et m'a rappelé quelque chose que je souhaite que nous ayons plus dans le monde C# .

autres que les liens fournis, il y a quelques bons liens sur C# et Java par rapport à ce sujet dans les réponses à cette question: Logic and its application to Collections.Generic and inheritance

Une sélection dont sont:

Questions connexes