parameter - Generics compila y ejecuta en Eclipse, pero no compila en javac
java type parameter (3)
Nota : Este es un spin-off del contrato Comparable y Comparator con respecto a null
Este código se compila y funciona bien en Eclipse ( 20090920-1017
)
import java.util.*;
public class SortNull {
static <T extends Comparable<? super T>>
Comparator<T> nullComparableComparator() {
return new Comparator<T>() {
@Override public int compare(T el1, T el2) {
return
el1 == null ? -1 :
el2 == null ? +1 :
el1.compareTo(el2);
}
};
}
public static void main(String[] args) {
List<Integer> numbers = new ArrayList<Integer>(
Arrays.asList(3, 2, 1, null, null, 0)
);
Comparator<Integer> numbersComp = nullComparableComparator();
Collections.sort(numbers, numbersComp);
System.out.println(numbers);
// "[null, null, 0, 1, 2, 3]"
List<String> names = new ArrayList<String>(
Arrays.asList("Bob", null, "Alice", "Carol")
);
Comparator<String> namesComp = nullComparableComparator();
Collections.sort(names, namesComp);
System.out.println(names);
// "[null, Alice, Bob, Carol]"
}
}
Y, sin embargo, no se compila en javac 1.6.0_17
. Este es el mensaje de error:
SortNull.java:17: incompatible types; no instance(s) of type variable(s) T exist
so that java.util.Comparator<T> conforms
to java.util.Comparator<java.lang.Integer>
found : <T>java.util.Comparator<T>
required: java.util.Comparator<java.lang.Integer>
Comparator<Integer> numbersComp = nullComparableComparator();
SortNull.java:25: incompatible types; no instance(s) of type variable(s) T exist
so that java.util.Comparator<T> conforms
to java.util.Comparator<java.lang.String>
found : <T>java.util.Comparator<T>
required: java.util.Comparator<java.lang.String>
Comparator<String> namesComp = nullComparableComparator();
2 errors
¿Alguien puede explicar por qué la discrepancia? ¿Es esto un error? Si es así, ¿quién tiene el error?
Este es un error confirmado: ID de error 6468354 . Aquí hay un extracto de relevancia:
Este problema es causado por el hecho de que a veces la implementación de JLS3 15.12.2.8 de javac ignora los límites recursivos, a veces no (como en este caso). Cuando los límites recursivos contienen comodines, dichos límites se incluyen al calcular las variables de tipo no infringido. Esto hace que la
test (Integer <: Comparable<? super T>
subsiguiente de subtipificacióntest (Integer <: Comparable<? super T>
dondeT
es una variable de tipo a inferir).Se solucionará después de 6369605
Me ha pasado lo mismo en WinXP con 1.6.0_13. Ah, bueno, me quedaré usando Eclipse :)
Puede solucionar esto especificando explícitamente la clase genérica:
Comparator<String> namesComp = Stack.<String>nullComparableComparator();
Tuve un problema similar y me actualicé de jdk1.6.0_16 a jdk1.6.0_23 y desapareció sin ningún cambio de código.