2010-02-22 12 views
17

Estoy usando genéricos bastante tiempo pero nunca he usado construcciones como List<? super T>.¿Puede alguien explicar qué significa <? super T> y cuándo debe usarse y cómo esta construcción debe cooperar con <T> y <? extends T>?

¿Qué significa? ¿Cómo usarlo? ¿Cómo se ve después del borrado?

También me pregunto: ¿es algo estándar en la programación genérica (programación de plantillas?) O simplemente es una 'invención' de Java? ¿C#, por ejemplo, permite construcciones similares?

Respuesta

9

Este constructo se utiliza cuando desea consumir elementos de una colección en otra colección. P.ej. tiene un Stack genérico y desea agregar un método popAll que toma una Colección como parámetro y saca todos los elementos de la pila. Por el sentido común, el código debe ser legal:

Stack<Number> numberStack = new Stack<Number>(); 
Collection<Object> objects = ... ; 
numberStack.popAll(objects); 

pero compila solamente si se define popAll así:

// Wildcard type for parameter that serves as an E consumer 
public void popAll(Collection<? super E> dst) { 
    while (!isEmpty()) 
    dst.add(pop()); 
} 

La otra cara de la moneda es que pushAll deberían definirse así:

// Wildcard type for parameter that serves as an E producer 
public void pushAll(Iterable<? extends E> src) { 
    for (E e : src) 
    push(e); 
} 

actualización: Josh Bloch se propaga este mnemotécnico para ayudarle a recordar qué tipo de comodín de usar:

PECS siglas de productor-extiende, consumidor-super.

Para obtener más información, consulte Effective Java 2nd Ed., Item 28.

+0

Java efectivo es genial, pero todavía no tengo la 2da edición (( – Roman

+0

@Roman puede descargar el capítulo sobre Genéricos del enlace que agregué :-) –

+0

Gracias, lo leeré. ¿No es así? saber si hay otros "capítulos de muestra" disponibles de forma gratuita? – Roman

4

Esto se denomina "comodín delimitado". Está muy bien explicado in the official tutorial.

Como se indica en el tutorial, por lo tanto saben que la lista contiene objetos de exactamente un subtipo de T

Por ejemplo List<? extends Number> puede contener sólo Integer s o sólo Long s, pero no ambos.

+2

' List numbers = Arrays.asList (1,5L); 'compila muy bien. Entonces la lista' numbers' contiene tanto el Int como el Long. ¿Qué me falta en la última línea de tu respuesta? – Geek

2

Estas cosas son conocidas, en teoría tipo, como varianza, con <? extends T> ser una notación co-variante, y <? super T> ser una notación contra-variante. La explicación más simple es que ? se puede reemplazar por cualquier tipo que se extienda T en la notación co-variante, y ? se puede reemplazar por cualquier tipo que T se extienda en la contravariante.

El uso de contra-varianza y contradicción es mucho más difícil de lo que parece al principio, especialmente porque la varianza "alterna" dependiendo de la posición.

Un ejemplo simple sería una clase de función. Supongamos que tiene una función que toma un A y devuelve un B. La notación correcta para esto sería decir que A es contravariante y B os co-variantes.Para entender mejor cómo este es el caso, vamos a considerar un método - llamémoslo g - que recibe esta clase hipotética función , donde se supone que f para recibir una Arc2D y devolver una Shape.

Dentro g, este f se llama el paso de una Arc2D y el valor de retorno se utiliza para inicializar un Area (que espera un Shape).

Ahora, supongamos que el f que pasa recibe Shape y devuelve Rectangle2D. Desde un Arc2D es un también un Shape, entonces g no obtendrá un error pasar una Arc2D a f, y desde un Rectangle2D es también un Shape, entonces se puede pasar al constructor Area 's.

Si intenta invertir cualquiera de las varianzas o cambiar los tipos esperado y real en ese ejemplo, verá que falla. No tengo tiempo ahora mismo para escribir este código, y mi Java está bastante oxidada en cualquier caso, pero veré lo que puedo hacer más tarde, si nadie tiene la amabilidad de hacerlo primero.

0

Las preguntas frecuentes de Java Generics tienen una buena explicación sobre los genéricos de Java. Consulte la pregunta What is a bounded wildcard? que explica el uso de la construcción "? Super T" en detalle.

Cuestiones relacionadas