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.