Genéricos de Java: firma Collections.max() y comparador
generics comparator (3)
Entiendo el principio get y put para colecciones: si un método toma una colección en la que escribirá un tipo T, el parámetro tiene que ser Collection<? super T>
Collection<? super T>
, mientras que si lee un tipo T desde, el parámetro tiene que ser Collection<? extends T>
Collection<? extends T>
.
Pero podría alguien explicar la firma Collections.max()
:
public static <T> T max(Collection<? extends T> coll,
Comparator<? super T> comp)
En particular, ¿por qué es Comparator<? super T>
Comparator<? super T>
lugar de Comparator<? extends T>
Comparator<? extends T>
?
El PECS mnemotécnico de Josh Bloch es útil aquí. Lo que representa:
El productor se extends
, el consumidor super
Esto significa que cuando un tipo parametrizado se pasa a un método producirá instancias de T
(se recuperarán de alguna manera) ? extends T
? extends T
debe usar ? extends T
, ya que cualquier instancia de una subclase de T
también es T
Cuando un tipo parametrizado que se pasa a un método consumirá instancias de T
(se pasarán a él para hacer algo) ? super T
debe usarse ? super T
porque una instancia de T
puede pasarse legalmente a cualquier método que acepte algún supertipo de T
Un Comparator<Number>
podría usarse en una Collection<Integer>
, por ejemplo. ? extends T
? extends T
no funcionaría, porque un Comparator<Integer>
no podría operar en una Collection<Number>
.
Editar: Para aclarar un poco más sobre get / put (producir / consumir):
public T something();
^
Lo anterior es un método que produce T
public void something(T t);
^
Lo anterior es un método que consume T
"Producer extends
, Consumer super
" se aplica a cómo el método al que se va a pasar un objeto parametrizado va a usar ese objeto. En el caso de Collections.max()
, los elementos se recuperarán de la Collection
, por lo que es un productor. Esos elementos se pasarán como argumentos al método en Comparator
, por lo que es un consumidor.
El Comparador consume un par de Ts y produce un int. La colección produce los Ts que consume el comparador.
Súper consume, extiende produce.
En relación con el principio get y put, get produce y pone consume.
El comparador debe poder tomar una T
como argumento.