sort ordering collection java generics collections comparable

java - ordering - Declaración de Collections.sort(): ¿por qué<? super T> en lugar de<T>



short collection java (3)

Se diferencian porque ? super T ? super T es menos restrictivo que T Es un comodín de límite inferior (el Tutorial de Java vinculado dice, en parte)

El término List<Integer> es más restrictivo que List<? super Integer> List<? super Integer> porque el primero coincide con una lista de tipo Integer solamente, mientras que el último coincide con una lista de cualquier tipo que es un supertipo de Integer .

Reemplace Integer con T y significa una T o un java.lang.Object .

¿Por qué Collections.sort(List<T>) tiene la firma:

public static <T extends Comparable<? super T>> void sort(List<T> list)

y no :

public static <T extends Comparable<T>> void sort(List<? extends T> list)

  • Entiendo que ambos servirían para el mismo propósito; Entonces, ¿por qué los desarrolladores del framework usaron la primera opción?
  • ¿O son estas declaraciones realmente diferentes?

Su firma propuesta probablemente funcionaría en Java-8. Sin embargo, en las versiones anteriores de Java, la inferencia de tipos no era tan inteligente. Tenga en cuenta que tiene la List<java.sql.Date> . Tenga en cuenta que java.sql.Date amplía java.util.Date que implementa Comparable<java.util.Date> . Cuando compilas

List<java.sql.Date> list = new ArrayList<>(); Collections.sort(list);

Funciona perfectamente en Java-7. Aquí se infiere que T es java.sql.Date que es en realidad Comparable<java.util.Date> Comparable<? super java.sql.Date> que es Comparable<? super java.sql.Date> Comparable<? super java.sql.Date> . Sin embargo, vamos a probar su firma:

public static <T extends Comparable<T>> void sort(List<? extends T> list) {} List<java.sql.Date> list = new ArrayList<>(); sort(list);

Aquí T debe inferirse como java.util.Date . Sin embargo, la especificación de Java 7 no permite tal inferencia. Por lo tanto, este código se puede compilar con Java-8, pero falla cuando se compila bajo Java-7:

Main.java:14: error: method sort in class Main cannot be applied to given types; sort(list); ^ required: List<? extends T> found: List<Date> reason: inferred type does not conform to declared bound(s) inferred: Date bound(s): Comparable<Date> where T is a type-variable: T extends Comparable<T> declared in method <T>sort(List<? extends T>) 1 error

La inferencia de tipos se mejoró enormemente en Java-8. El capítulo 18 separado de JLS está dedicado a él ahora, mientras que en Java-7 las reglas were mucho más simples.


// 0 public static <T extends Comparable<? super T>> void sort0(List<T> list) // 1 public static <T extends Comparable<T>> void sort1(List<? extends T> list)

Estas firmas difieren porque imponen requisitos diferentes en la relación entre el tipo T y el argumento de tipo Comparable en la definición de T

Supongamos, por ejemplo, que tiene esta clase:

class A implements Comparable<Object> { ... }

Entonces si tienes

List<A> list = ... ; sort0(list); // works sort1(list); // fails

La razón por la que sort1 falla es que no hay un tipo T que sea comparable a sí mismo y que sea, o sea un supertipo de, el tipo de la lista.

Resulta que la clase A tiene un formato incorrecto, porque los objetos que son Comparable deben cumplir ciertos requisitos. En particular, revertir la comparación debería revertir el signo del resultado. Podemos comparar una instancia de A con un Object pero no al revés, por lo que se viola este requisito. Pero tenga en cuenta que este es un requisito de la semántica de Comparable y no está impuesto por el sistema de tipos. Teniendo en cuenta únicamente el sistema de tipos, las dos declaraciones de sort son realmente diferentes.