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 queList<? super Integer>List<? super Integer>porque el primero coincide con una lista de tipoIntegersolamente, mientras que el último coincide con una lista de cualquier tipo que es un supertipo deInteger.
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.