2009-03-06 12 views

Respuesta

16

No hay diferencia práctica en términos de lo que puede hacer cuando tiene uno de ellos, porque el parámetro de tipo solo se usa en una posición de "salida". Por otro lado, hay una gran diferencia en términos de lo que puede usar como uno de ellos.

Supongamos que tiene Enumeration<JarEntry> - no pudo pasar esto a un método que tomó Enumeration<ZipEntry> como uno de sus argumentos. Usted podría pasarlo a un método tomando Enumeration<? extends ZipEntry> sin embargo.

Es más interesante cuando tienes un tipo que utiliza el parámetro tipo en las posiciones de entrada y salida, siendo el ejemplo más obvio el List<T>. Aquí hay tres ejemplos de métodos con variaciones en un parámetro. En cada caso, intentaremos obtener un elemento de la lista y agregar otro.

// 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); 
} 

Para más detalles, lea:

+0

ZipEntrySubclass como JarEntry (¿por qué ZipFile.entries usa un comodín)? –

+0

Gracias Tom - editaré mi respuesta :) –

4

Sí, directamente de uno de los sun generics tutorials:

Aquí Shape es una clase abstracta con tres subclases: Círculo, Rectángulo, y Triángulo.

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

Vale la pena señalar que el método draw() sólo puede ser llamado en las listas de forma y no puede ser llamado en una lista del círculo, rectángulo, triángulo y para ejemplo. Con el fin de tener el método aceptar cualquier tipo de forma, debe ser escribirse como sigue:

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

Esta es la segunda vez esta semana que Jon Skeet ha recibido una respuesta justo antes que yo. Propongo que nos refiramos a esto como Skeeting. – GaryF

+0

suena bien. ¿Cuál sería el tiempo pasado? Sket? "¡Jon Skeet me trajo OTRA VEZ!" :) – Epaga

+0

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

0

Ahora se acaba de ir y me recordó algo que nos hubiera gustado más en el C# mundo .

Aparte de los enlaces proporcionados, hay algunos buenos enlaces sobre C# y Java en relación con este tema en las respuestas a esta pregunta: Logic and its application to Collections.Generic and inheritance

Una selección de las cuales son:

Cuestiones relacionadas