Tengo un par de preguntas sobre comodines genéricos en Java:Java Generics (comodines)
¿Cuál es la diferencia entre
List<? extends T>
yList<? super T>
?¿Qué es un comodín delimitado y qué es un comodín ilimitado?
Tengo un par de preguntas sobre comodines genéricos en Java:Java Generics (comodines)
¿Cuál es la diferencia entre List<? extends T>
y List<? super T>
?
¿Qué es un comodín delimitado y qué es un comodín ilimitado?
En su primera pregunta, <? extends T>
y <? super T>
son ejemplos de comodines acotadas. Un comodín ilimitado se ve como <?>
, y básicamente significa <? extends Object>
. Significa vagamente que el genérico puede ser de cualquier tipo. Un comodín acotada (<? extends T>
o <? super T>
) impone una restricción en el tipo diciendo que o bien tiene que extender un tipo específico (<? extends T>
se conoce como un límite superior), o tiene que ser un antepasado de un tipo específico (<? super T>
es conocido como un límite inferior).
Los tutoriales de Java tienen algunas explicaciones bastante buenas de los genéricos en los artículos Wildcards y More Fun with Wildcards.
Solo para hacerlo bien, si A es incorrecto? –
Si por A para limitar sus elecciones a A o B. –
y en ese caso si digo super C> ¿cuál sería la diferencia? –
Si tiene una jerarquía de clases A, B es una subclase de A, y C y D ambos son subclase de B, como a continuación
class A {}
class B extends A {}
class C extends B {}
class D extends B {}
Entonces
List<? extends A> la;
la = new ArrayList<B>();
la = new ArrayList<C>();
la = new ArrayList<D>();
List<? super B> lb;
lb = new ArrayList<A>(); //fine
lb = new ArrayList<C>(); //will not compile
public void someMethod(List<? extends B> lb) {
B b = lb.get(0); // is fine
lb.add(new C()); //will not compile as we do not know the type of the list, only that it is bounded above by B
}
public void otherMethod(List<? super B> lb) {
B b = lb.get(0); // will not compile as we do not know whether the list is of type B, it may be a List<A> and only contain instances of A
lb.add(new B()); // is fine, as we know that it will be a super type of A
}
Un comodín acotada es como ? extends B
donde B es un tipo. Es decir, el tipo es desconocido pero se puede colocar un "límite" sobre él. En este caso, es limitado por alguna clase, que es una subclase de B.
+1 por ejemplos. –
gran ejemplo, gracias – Peter
Josh Bloch también tiene una buena explicación de cuándo utilizar super
y extends
en este google io video talk donde menciona los Productor extends
de consumo super
mnemotécnica .
De las diapositivas de la presentación:
Supongamos que desea agregar métodos a granel a
Stack<E>
void pushAll(Collection<? extends E> src);
- src es un productor E
void popAll(Collection<? super E> dst);
- DST es un consumidor E
He leído el libro de Bloch, pero todavía no puedo ver la diferencia entre extends y super en este caso particular. –
Mira el video, creo que está bastante claro. Además, creo que deberías hacer otra pregunta sobre este "cuál es la diferencia entre List extends T> y List super T>" donde es de esperar que obtengas más respuestas. (si lo hace, agregue un enlace desde aquí) – blank
Camas: por qué no incluir el ejemplo en esta respuesta para que sea completo y independiente. Los enlaces son efímeros. –
Es posible que en ocasiones desee restringir los tipos de tipos que pueden pasar a un parámetro de tipo. Por ejemplo, un método que opera con números solo podría querer aceptar instancias de Number o sus subclases. Esto es para lo que son los parámetros de tipo delimitados.
Collection<? extends MyObject>
significa que puede aceptar todos los objetos que tienen es, un relación con MiObjeto (es decir,cualquier objeto que sea un tipo de myObject o podemos decir cualquier objeto de cualquier subclase de MyObject) o un objeto de la clase MyObject.
Por ejemplo:
class MyObject {}
class YourObject extends MyObject{}
class OurObject extends MyObject{}
Entonces,
Collection<? extends MyObject> myObject;
sólo aceptará MyObject o hijos de MyObject (es decir, cualquier objeto de OurObject tipo o YourObject o MyObject, pero no cualquier objeto de superclase de MyObject).
En general,
Si una estructura contiene elementos con un tipo de forma
? extends E
, podemos obtener los elementos de la estructura, pero no podemos poner elementos en la estructura
List<Integer> ints = new ArrayList<Integer>();
ints.add(1);
ints.add(2);
List<? extends Number> nums = ints;
nums.add(3.14); // compile-time error
assert ints.toString().equals("[1, 2, 3.14]");
Para poner elementos en la estructura que necesitamos otro tipo de comodines llamada Wildcards with super
,
List<Object> objs = Arrays.<Object>asList(2, 3.14, "four");
List<Integer> ints = Arrays.asList(5, 6);
Collections.copy(objs, ints);
assert objs.toString().equals("[5, 6, four]");
public static <T> void copy(List<? super T> dst, List<? extends T> src) {
for (int i = 0; i < src.size(); i++) {
dst.set(i, src.get(i));
}
}
Los comodines genéricos se crean para que los métodos que operan en Colección sean más reutilizables. Por ejemplo, si un método tiene un parámetro List<A>
, solo podemos proporcionar List<A>
a este método. Es una pérdida para la funcion de este método en algunas circunstancias:
List<A>
, a continuación, se nos debería permitir dar List<A-sub>
a este método. (Debido a que A-sub IS a)List<A>
, entonces se nos debe permitir dar List<A-super>
a este método. (Debido a que A es un A-súper)Por ejemplo tenemos el siguiente jerarquía de clases
objeto < - Un < - B, C
Debe utilizar List <? extends A>
(superior obligado) si va a lea de la lista
Cuando sabe que las instancias en la colección son de instancias de A o de subclases de A, es seguro para leer las instancias de la colección y convertirlas en instancias A.
Usted no puede insertar elementos en la lista, porque no sabe si la lista se escribe a la clase A, B o C.
Debe utilizar List <? super A>
(límite inferior) si se va a inserción en la lista
Cuando se sabe que la lista se escribe a los puntos A, o una superclase de A, es seguro para insertar instancias de A o subclases de A (por ejemplo, B o C) en la lista.
Usted no puede leer de la lista, excepto si arroja los objetos leídos a Objeto. Los elementos ya presentes en la lista podrían ser de cualquier tipo que sea una A o una superclase de A, pero no es posible saber exactamente qué clase es.
Leer más aquí - http://tutorials.jenkov.com/java-generics/wildcards.html
En el caso de que [Ted Gao] (http://stackoverflow.com/users/970122/ted-gao) [respuesta] (http://stackoverflow.com/a/9446233/2476755) se elimina (ya que era solo un enlace), aquí está la [publicación de blog] (http://ted-gao.blogspot.com/search/label/Java%20Generics) a la que enlaza . – royhowie