Generics компилируется и запускается в Eclipse, но не компилируется в javac
Примечание. Это ответвление от контракта Comparable и Comparator относительно нулевого значения.
Этот код компилируется и отлично работает в 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]"
}
}
И все же это не компилируется на javac 1.6.0_17
, Это сообщение об ошибке:
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
Может кто-нибудь объяснить, почему расхождение? Это ошибка? Если так, у кого есть ошибка?
3 ответа
Это подтвержденная ошибка: идентификатор ошибки 6468354. Вот выдержка из актуальности:
Эта проблема вызвана тем фактом, что иногда реализация JLS3 15.12.2.8 в javac игнорирует рекурсивные границы, иногда нет (как в этом случае). Когда рекурсивные границы содержат подстановочные знаки, такие границы включаются при вычислении переменных неинтерференционного типа. Это делает последующие подтипы
test (Integer <: Comparable<? super T>
гдеT
переменная типа, которая будет выведена)Будет исправлено после 6369605
Приходил ко мне и на WinXP с 1.6.0_13. Ах, хорошо, я просто буду использовать Eclipse:)
Вы можете обойти это, явно указав универсальный класс:
Comparator<String> namesComp = Stack.<String>nullComparableComparator();
У меня была похожая проблема, и я обновил ее с jdk1.6.0_16 до jdk1.6.0_23, и она ушла без каких-либо изменений кода.